TypeScript: queue thinking and writing

When implementing a number of functional requirements, often encounter some waiting to be executed or rely on a number of related operations after the end of a certain purpose.

For example: a certain period of a day of military training in a school is, the school a total of n classes, in a day (24 hours) to complete the physical training classes all the provisions of their respective classes. Suppose a class to conduct a physical training at some point, this class there are n people queuing divided into n rows xn columns, the following figure shows:

 

 

 The relevant conditions above examples to consider:

Condition 1, a school n classes may need to take into account the lack of campus land, the site can only provide a physical training class, namely: a class or multiple classes be conducted, if a class is carried out, it is the first in first out , after the last in principle. If multiple classes are conducted, that there is no principle (I do not know), according to different needs, also have different implementations, but also affect subsequent development.

Condition 2, the time factor, whether all the provisions n days to complete the class or not there is the time factor, you can complete each class time to complete a physical training is how much it takes, whether it can be completed within the time specified by individual classes, whether select multiple classes conducted.

Condition 3, if a sick instructor or instructors and students can not continue to assault resulting in physical training, this case is considered delayed, whether directly or in a queue to remove the last class execution.

Condition 4, each class of physical training are the same or different randomly selected items. Like suppose projects, such as performing push-ups fitness training, so all students performed simultaneously or alternately executed.

 

The above example is a two-dimensional array of similar queues in the realization of the demand, we must take into account all possible, if you want to be careful enough, every minute will refactor code structure. If it is purely to achieve a certain class of students queue, then consider not so much.

I simply to build a queue of writing (after the implementation of a complete execution to another).

1, a first name to save the execution queue container

 

 

 2, the process of naming-related operations, according to their own needs saving, no you can not write

 

 

 3, write a create function, used to trigger the execution queue

 

 

 4, the detection function detects whether the execution has been completed or is

 

 

 5, to perform functions, mainly related to the implementation of this logic operations, such as the above example of how a student performed push-ups, made a number of push-ups, it is done after adding a callback function or event notification has released a complete execution

以上目前只是实现了一个简单一维队列的底层架构,具体思路。根据自己项目需求不同,再往里面添油加醋完成目的。以下附上我做的一个新手引导队列 一个二维数组队列作为参考

import Conf, {Guide_combinationCfg, Guide_stepCfg, GuideCfg} from "../config/Conf";
import {UIMgr} from "./UIMgr";
import {LayerMgr} from "./LayerMgr";
import {LogicDispatcher} from "../../core/event/LogicDispatcher";
import GameEvent from "../main/events/GameEvent";
import GuideEffectView from "../main/view/guide/GuideEffectView";
import GuideTouchView from "../main/view/guide/GuideTouchView";
import GuideDialogueView from "../main/view/guide/GuideDialogueView";
import GLocalStorage from "../main/global/GLocalStorage";
import Global from "../main/global/Global";

/**
 * 新手引导管理类。检测、播放、停止都在此类进行
 * @author DuckKing
 * @Date: 2019-12-18 19:53:11
 * @Last Modified by: DuckKing
 * @Last Modified time: 2019-12-30 20:45:11
 * */
export default class GuideMgr
{
    private static _instance: GuideMgr;
    public static get instance(): GuideMgr
    {
        if(!this._instance)
            this._instance = new GuideMgr();
        return this._instance;
    }

    /** 新手引导队列*/
    public list: number[] = [];
    /** 新手引导步骤队列。*/
    public steps: number[] = [];
    /** 当前要执行的新手指引id*/
    public curGuideId: number = 0;
    /** 当前执行的新手指引步骤id*/
    public curStepId: number = 0;
    /** 当前是否正在执行新手指引*/
    public curRunGuide: boolean;
    /** 当前是否正在执行某个步骤*/
    public curRunStep: boolean;

    /** 当前已打开的组件面板*/
    private _panels: {[id:  number]: GuideTouchView | GuideDialogueView | GuideEffectView } = [];

    /**
     * 检测新手引导
     * @param id
     */
    public checkGuide(id: number): void
    {
        let key: string = `${Global.heroVo.name}${GLocalStorage.GUIDE_SAVE}${id}`;
        if(!GLocalStorage.getItem(key))
        {
            let cfg: GuideCfg = Conf.guide[id];
            if(cfg) this.createGuide(id);
        }
    }

    /**
     * 创建一个新手引导
     * @param id
     */
    public createGuide(id: number): void
    {
        this.list.push(id);
        this.checkIsRunGuide();
    }

    /**
     * 检测当前是否正在执行引导
     */
    public checkIsRunGuide(): void
    {
        if(this.curRunGuide) return;

        if(this.list.length > 0)
        {
            this.curGuideId = this.list.shift();
            this.playGuide(this.curGuideId);
        }
        else
        {
            let key: string = `${Global.heroVo.name}${GLocalStorage.GUIDE_SAVE}${this.curGuideId}`;
            GLocalStorage.setItem(key, "true");
            LogicDispatcher.event(GameEvent.GUIDE_OVER);
        }
    }

    /**
     * 播放一个新手引导
     * @param guideId
     */
    public playGuide(guideId: number): void
    {
        this.curRunGuide = true;
        this.curGuideId = guideId;

        let cfg: GuideCfg = Conf.guide[guideId];
        for(let temp of cfg.steps)
        {
            this.steps.push(temp);
        }

        this.checkIsRunStep();

        LogicDispatcher.on(GameEvent.GUIDE_OVER, this, this.onGuideComplete);
    }

    /**
     * 检测当前是否正在执行步骤
     */
    public checkIsRunStep(): void
    {
        if(this.curRunStep) return;

        //检测当前是否还有步骤未执行。。若没有继续检测上一级
        if(this.steps.length > 0)
        {
            this.curStepId = this.steps.shift();
            this.playStep(this.curStepId);
        }
        else
        {
            this.curRunGuide = false;
            this.checkIsRunGuide();
        }
    }

    /**
     * 播放一个步骤
     * @param stepId 步骤id
     */
    public playStep(stepId: number): void
    {
        this.curStepId = stepId;
        this.curRunStep = true;

        let cfg: Guide_stepCfg = Conf.guide_step[stepId];
        for(let i: number = 0; i < cfg.group.length; i++)
        {
            let groupId: number = cfg.group[i];
            let std: Guide_combinationCfg = Conf.guide_combination[groupId];

            let value: any = std.value;
            let node: Laya.Node;
            if(value)
            {
                if(value.btn)
                {
                    node = UIMgr.instance.getElementHandle(LayerMgr.rootLayer, value.btn);
                }
                else if(value.list)
                {
                    node = (UIMgr.instance.getElementHandle(LayerMgr.rootLayer, value.list) as Laya.List).cells[value.index];
                }
            }

            let panel: GuideTouchView | GuideEffectView | GuideDialogueView;
            switch (std.type)
            {
                //点击面板
                case 1:
                    panel = new GuideTouchView(std, node);
                    break;
                //特效面板
                case 2:
                    panel = new GuideEffectView(std, node);
                    break;
                //战斗面板
                case 3:
                    break;
                //对白面板
                case 4:
                    panel = new GuideDialogueView(std, node);
                    break;
            }
            this._panels[std.type] = panel;
            LayerMgr.rootLayer.addChild(panel);
        }

        if(cfg.lastDelay)
        {
            Laya.timer.once(cfg.lastDelay, this, this.closePanel)
        }

        LogicDispatcher.on(GameEvent.GUIDE_STEP_OVER, this, this.onStepComplete);
    }

    /**
     * 步骤配置里面如果配置了n秒后自动关闭面板
     */
    private closePanel(): void
    {
        for(let i in this._panels)
        {
            let temp = this._panels[i];
            LayerMgr.rootLayer.removeChild(temp);
        }
        LogicDispatcher.event(GameEvent.GUIDE_STEP_OVER);
    }

    /**
     * 某个新手指引结束后的回调函数
     */
    private onGuideComplete(): void
    {
        this.curRunGuide = false;

        let that = this;
        let std: GuideCfg = Conf.guide[this.curGuideId];
        Laya.timer.once(std.startDelay ? std.startDelay : 500, this, function() {
            that.checkIsRunGuide();
        })
    }

    /**
     * 某个步骤结束后的回调函数
     */
    private onStepComplete():void
    {
        this.curRunStep = false;

        for(let i in this._panels)
        {
            let temp: GuideTouchView | GuideDialogueView | GuideEffectView = this._panels[i];
            switch (i)
            {
                case "1":
                    (temp as GuideTouchView).clear();
                    break;
                case "2":
                    break;
            }

            LayerMgr.rootLayer.removeChild(temp);
        }

        let that = this;
        let std: Guide_stepCfg = Conf.guide_step[this.curStepId];
        Laya.timer.once(std.startDelay ? std.startDelay : 500, this, function () {
            that.checkIsRunStep();
        })
    }
}
View Code

Guess you like

Origin www.cnblogs.com/Duck-King/p/12150004.html