示例#1
0
    /// <summary>
    ///
    /// add delivery paths for each selected vehicle to the scene
    ///
    /// </summary>
    protected void RefreshPaths()
    {
        connectorMap.Clear();

        // remove all paths
        GameObject[] objs = GameObject.FindGameObjectsWithTag("link");
        foreach (GameObject go in objs)
        {
            Destroy(go);
        }

        // remove play icons for the business view (probably should move this to the
        // business interface code)
        objs = GameObject.FindGameObjectsWithTag("playicons");
        foreach (GameObject go in objs)
        {
            Destroy(go);
        }

        // for all paths
        for (int i = 0; i < plan.paths.Count; i++)
        {
            // thicken selected path
            float scalePath = 0.12f;
            if (selectedPathIndex == i)
            {
                scalePath = 0.40f;
            }


            // for each path segment not starting or ending at the warehouse
            for (int j = 1; j < plan.paths[i].customers.Count; j++)
            {
                Address    addressA = plan.paths[i].customers[j - 1].address;
                Address    addressB = plan.paths[i].customers[j].address;
                GameObject obj      = CreateCylinderBetweenPoints(ScaleInScene(new Vector3(addressA.x, 1, addressA.z)), ScaleInScene(new Vector3(addressB.x, 1, addressB.z)), scalePath, i == selectedPathIndex ? Color.cyan : Color.white, plan.paths[i].customers[j].deliverytime, "link");
                connectorMap[obj] = new Customer[] { plan.paths[i].customers[j - 1], plan.paths[i].customers[j] };
            }

            // get paths to and from warehouse
            if (plan.paths[i].customers.Count > 0)
            {
                Address    addressB = plan.paths[i].customers[0].address;
                GameObject obj      = CreateCylinderBetweenPoints(ScaleInScene(new Vector3(plan.paths[i].warehouse.address.x, 1, plan.paths[i].warehouse.address.z)), ScaleInScene(new Vector3(addressB.x, 1, addressB.z)), scalePath, i == selectedPathIndex ? Color.cyan : Color.white, plan.paths[i].customers[0].deliverytime, "link");
                connectorMap[obj] = new Customer[] { null, plan.paths[i].customers[0] };
                Address addressA = plan.paths[i].customers[plan.paths[i].customers.Count - 1].address;
                obj = CreateCylinderBetweenPoints(ScaleInScene(new Vector3(addressA.x, 1, addressA.z)), ScaleInScene(new Vector3(plan.paths[i].warehouse.address.x, 1, plan.paths[i].warehouse.address.z)), scalePath, i == selectedPathIndex ? Color.cyan : Color.white, 0.0f, "link");
                connectorMap[obj] = new Customer[] { plan.paths[i].customers[plan.paths[i].customers.Count - 1], null };
            }
        }

        // Calculates the resulting manual or AI based solutions. The ortools returns results
        // where if there is a time window, it says the the travel time is from 0 to 4, instead of 3.5 to
        // 4, which results in incorrect calculations, so just use the below to get the correct metrics
        planCalculation = new PlanCalculation(plan, scaleSceneFactor, business);
        planCalculation.calculate();
        planMetricsStr = planCalculation.getInfoString();
        overbudget     = planCalculation.getStartupCost() > budget;
    }
    /// <summary>
    ///
    /// GUI controls for the business view
    ///
    /// </summary>
    protected override void OnGUICustom()
    {
        Rect rect = Camera.main.pixelRect;

        // add toolbar button to load the current market setup
        if (GUI.Button(businessLoadCurrentMarketRect, new GUIContent(GUIHelpers.resetdesignimage, "Load Current Market")))
        {
            RemovePaths();
            DataInterface.GetScenario();

            Capture.Log("LoadCurrentScenario", Capture.BUSINESS);
            playClick();
        }

        // submit market button
        if (GUI.Button(submitScenarioRect, new GUIContent("Submit", "Submit the Selected Customers to Your Planners")))
        {
            GUIAssets.PopupButton.popupPanelID = "SubmitBusiness";
            GUIAssets.PopupButton.showing      = true;
            GameObject.Find("SubmitBusiness").GetComponent <Canvas>().enabled = true;
        }

        // button for the information panel
        if (GUI.Button(infoRect, new GUIContent(GUIHelpers.infoimage, "Show Information Panel")))
        {
            showHelpInfoPanel = !showHelpInfoPanel;
            playClick();
            GameObject.Find("helpcanvasbusiness").GetComponent <Canvas>().enabled = showHelpInfoPanel;
            Capture.Log("ToggleInfoPanel:" + showHelpInfoPanel, business ? Capture.BUSINESS : Capture.PLANNER);
        }

        // add the plan list on the right side panel
        int counter      = 0;
        int scrollheight = (int)Math.Max(rect.height - 250, 200);

        businessPlansRect = new Rect(rect.width - 180, 10, 170, scrollheight);
        GUI.Box(businessPlansRect, new GUIContent("    Team Plans", "Select a Plan To Open"));
        scrollPositionOperationplans = GUI.BeginScrollView(new Rect(rect.width - 174, 40, 164, scrollheight), scrollPositionOperationplans, new Rect(0, 0, 140, 20 + loadedPlans.Count * 21));

        // for each plan add a toggle button and a button to load
        foreach (int id in loadedPlans.Keys)
        {
            // adds a toggle button if the plan is fully loaded
            bool   loaded = loadedPlans[id].plan != null;
            string tag    = (!loaded ? "* " : "") + loadedPlans[id].tag;
            bool   val    = false;
            if (loaded)
            {
                val = GUI.Toggle(new Rect(0, 20 + 20 * counter, 24, 20), loadedPlans[id].selected, new GUIContent("", "Toggle in Dashboard"));
            }

            // if there is a change in plan selection
            if ((val && !loadedPlans[id].selected) || (!val && loadedPlans[id].selected))
            {
                RemovePlayIcons();

                loadedPlans[id].selected = val;
                if (!loadedPlans[id].selected)
                {
                    ShowMsg("Plan unselected : " + tag, false);
                }

                // code for a selected plan, probably do not need the loaded check, but kept it in
                if (loadedPlans[id].selected && loaded)
                {
                    // calculate the plan metrics
                    PlanCalculation calculation = new PlanCalculation(loadedPlans[id].plan, scaleSceneFactor, business);
                    calculation.calculate();

                    // add plan data to dashboard
                    DashboardData.PlanData planData = new DashboardData.PlanData();
                    planData.tag           = tag;
                    planData.profit        = calculation.getProfit();
                    planData.operatingCost = calculation.getOperatingCost();
                    planData.startupCost   = calculation.getStartupCost();
                    planData.deliveries    = calculation.getCustomers();;
                    planData.massDelivered = calculation.GetTotalWeightDelivered();
                    planData.parcelMass    = calculation.getTotalParcelDelivered();
                    planData.foodMass      = calculation.getTotalFoodDelivered();
                    DashboardData.addPlanData(loadedPlans[id].plan, planData);

                    ShowMsg("Plan selected : " + tag, false);
                }

                // hide or show the Play button if two plans are selected
                int selectedPlans = 0;
                foreach (int idkey in loadedPlans.Keys)
                {
                    if (loadedPlans[idkey].selected)
                    {
                        selectedPlans += 1;
                    }
                }
                playEnabled = (selectedPlans == 2);

                Capture.Log("SelectedPlan;" + tag + ";" + loadedPlans[id].selected, Capture.BUSINESS);
                playClick();
            }
            GUI.color = Color.white;


            // add GUI button to open a plan
            GUI.color = loaded ? Color.white : Color.gray;
            if (loaded)
            {
                // check for play color results
                if (loadedPlans[id].plan != null)
                {
                    if (loadedPlans[id].plan.Equals(winningPlayPlan))
                    {
                        GUI.color = Color.green;
                    }
                    else if (loadedPlans[id].plan.Equals(losingPlayPlan))
                    {
                        GUI.color = Color.red;
                    }
                }
            }

            // button to open the plan
            if (GUI.Button(new Rect(20, 20 + 20 * counter, 120, 20), tag))
            {
                if (loaded)
                {
                    userSelectedPlan = loadedPlans[id].plan;
                    OpenPlan(loadedPlans[id].plan);
                }
            }
            GUI.color = Color.white;
            counter  += 1;
        }
        GUI.EndScrollView();

        // add Play button
        if (playEnabled)
        {
            playRect = new Rect(rect.width - 120, scrollheight + 40, 80, 25);
            if (GUI.Button(playRect, new GUIContent("Play", "Play Two Selected Plans Against Each Other")))
            {
                Capture.Log("Play", business ? Capture.BUSINESS : Capture.PLANNER);
                play();
                playEnabled = false;
            }
        }

        // select the final plan button at the button left corner of the display if not already selected
        selectPlanRect = new Rect(160, rect.height - 50, 84, 24);
        if (!businessFinalPlanSelected)
        {
            if (GUI.Button(selectPlanRect, new GUIContent("Select Plan", "Select Final Plan for Your Team")))
            {
                // make sure that there are customers in a delivery plan, this should alway
                // have more than 0 customers
                int totalCustomers = 0;
                foreach (DataObjects.VehicleDelivery p in plan.paths)
                {
                    totalCustomers += p.customers.Count;
                }

                // make sure a plan with the correct market is selected
                bool correctMarket = false;
                try
                {
                    correctMarket = (RestWebService.market == plan.scenario.customers[0].market);
                } catch (Exception e)
                {
                    Debug.Log(e);
                }

                // a valid plan
                if (totalCustomers > 0 && correctMarket)
                {
                    GUIAssets.PopupButton.showing      = true;
                    GUIAssets.PopupButton.popupPanelID = "SubmitPlan";
                    GameObject.Find("SubmitPlan").GetComponent <Canvas>().enabled = true;
                }
                else
                {
                    GameObject.Find("popup").GetComponent <Canvas>().enabled           = true;
                    GameObject.Find("popupsuccess").GetComponent <Image>().enabled     = true;
                    GameObject.Find("popuperror").GetComponent <Image>().enabled       = true;
                    GameObject.Find("popuptext").GetComponent <TextMeshProUGUI>().text = !correctMarket ? "Plan Does Not Use the Current Market" : "Empty Plan";
                }
            }
        }


        // toggle button for the dashboard
        dashboardRect = new Rect(rect.width - 200, rect.height - 38, 28, 28);
        if (GUI.Button(dashboardRect, new GUIContent(GUIHelpers.dashboardimage, "Toggle The Dashboard View")))
        {
            dashboardView = !dashboardView;
            playClick();
            Capture.Log("DashboardView;" + dashboardView, business ? Capture.BUSINESS : Capture.PLANNER);
        }

        // add dashboard
        if (dashboardView)
        {
            // get selected plans
            List <Plan> selectedPlans = new List <Plan>();
            foreach (int id in loadedPlans.Keys)
            {
                if (loadedPlans[id].selected)
                {
                    selectedPlans.Add(loadedPlans[id].plan);
                }
            }

            // set billboard sizing variables
            float dashboardheight = Math.Min(100 + 20 * selectedPlans.Count, 200);
            float height          = Math.Min((dashboardheight - 100) / selectedPlans.Count, 20);
            float dashboardwidth  = Math.Max(3.0f * (rect.width - 454f) / 4.0f, 600);
            float width           = Math.Max((dashboardwidth - 60) / 8, 10);
            float dashboardx      = rect.width - 200 - dashboardwidth;
            float labelx          = dashboardx + 100;

            // add the outer box
            GUI.Box(new Rect(dashboardx, rect.height - dashboardheight - 10, dashboardwidth, dashboardheight), "");
            if (selectedPlans.Count > 0)
            {
                // add labels for each metric
                GUI.Label(new Rect(labelx, rect.height - dashboardheight + 20, width, 20), "Profit($)");
                GUI.Label(new Rect(labelx + 1 * (width + 4), rect.height - dashboardheight + 6, width, 40), "Oper\nCost($)");
                GUI.Label(new Rect(labelx + 2 * (width + 4), rect.height - dashboardheight + 6, width, 40), "StartUp\nCost($)");
                GUI.Label(new Rect(labelx + 3 * (width + 4), rect.height - dashboardheight + 20, width, 20), "Deliveries");
                GUI.Label(new Rect(labelx + 4 * (width + 4), rect.height - dashboardheight + 20, width, 20), "Mass(lb)");
                GUI.Label(new Rect(labelx + 5 * (width + 4), rect.height - dashboardheight + 20, width, 20), "Parcel(lb)");
                GUI.Label(new Rect(labelx + 6 * (width + 4), rect.height - dashboardheight + 20, width, 20), "Food(lb)");

                GUI.Label(new Rect(labelx, rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxProfit);
                GUI.Label(new Rect(labelx + 1 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxOperatingCost);
                GUI.Label(new Rect(labelx + 2 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxstartupCost);
                GUI.Label(new Rect(labelx + 3 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxDeliveries);
                GUI.Label(new Rect(labelx + 4 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxMassDelivered);
                GUI.Label(new Rect(labelx + 5 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxParcelMass);
                GUI.Label(new Rect(labelx + 6 * (width + 4), rect.height - dashboardheight + 40, width, 20), "Max:" + DashboardData.maxFoodMass);

                // add plan data
                for (int i = 0; i < selectedPlans.Count; i++)
                {
                    // get plan metric data
                    DashboardData.PlanData p = DashboardData.dashboardData[selectedPlans[i]];

                    // get y offset
                    float yOffset = 0;
                    if (height < 20)
                    {
                        yOffset = (20 - height) / 2;
                    }

                    // add the plan label, shorten the name if long
                    GUI.skin.label.alignment = TextAnchor.MiddleRight;
                    string planLabel = p.tag;
                    if (p.tag.Length > 14)
                    {
                        planLabel = p.tag.Substring(0, 14);
                    }
                    GUI.Label(new Rect(dashboardx, rect.height - dashboardheight + 60 + i * (height + 2) - yOffset, 90, 20), planLabel);
                    GUI.skin.label.alignment = TextAnchor.MiddleLeft;

                    // if there are play results, then shade based on winning and losing colors
                    GUIStyle boxStyle = Assets.GUIHelpers.lightgrayStyle;
                    if (selectedPlans[i].Equals(winningPlayPlan))
                    {
                        boxStyle = Assets.GUIHelpers.darkgreenStyle;
                    }
                    else if (selectedPlans[i].Equals(losingPlayPlan))
                    {
                        boxStyle = Assets.GUIHelpers.darkredStyle;
                    }

                    // add metric bars to display plan performance
                    GUI.Box(new Rect(labelx, rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.profit - DashboardData.minProfit) / (DashboardData.maxProfit - DashboardData.minProfit), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 1 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.operatingCost - DashboardData.minOperatingCost) / (DashboardData.maxOperatingCost - DashboardData.minOperatingCost), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 2 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.startupCost - DashboardData.minstartupCost) / (DashboardData.maxstartupCost - DashboardData.minstartupCost), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 3 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.deliveries - DashboardData.minDeliveries) / (DashboardData.maxDeliveries - DashboardData.minDeliveries), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 4 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.massDelivered - DashboardData.minMassDelivered) / (DashboardData.maxMassDelivered - DashboardData.minMassDelivered), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 5 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.parcelMass - DashboardData.minParcelMass) / (DashboardData.maxParcelMass - DashboardData.minParcelMass), height), "", boxStyle);
                    GUI.Box(new Rect(labelx + 6 * (width + 4), rect.height - dashboardheight + 60 + i * (height + 2), 2 + (width - 2) * (p.foodMass - DashboardData.minFoodMass) / (DashboardData.maxFoodMass - DashboardData.minFoodMass), height), "", boxStyle);
                }
            }
        }
    }