Vstupní data pro simulaci obchodního domu ========================================= Oddělení: jméno patro rychlost obsluhy ----------------------------------------- O papírnictví 0 5 O potraviny 0 15 O drogerie 0 6 O textil 1 15 O nábytek 2 20 O elektronika 3 5 O CD-DVD 3 4 Výtah jméno kapacita doba nastoupení doba vystoupení doba jízdy z patra do patra ----------------------------------------------------------------------------------------- V elefant 10 1 1 1 Zákazníci jméno příchod trpělivost seznam oddělení... ----------------------------------------------------------------------------------------- Z Adam 10 1 CD-DVD Z Alžběta 10 5 textil drogerie nábytek Z Bořík 10 1 papírnictví elektronika Z Barborka 10 1 CD-DVD papírnictví Z Cyril 10 2 potraviny papírnictví Z Cecilka 10 5 potraviny textil drogerie nábytek Z David 11 3 CD-DVD elektronika Z Dana 11 2 potraviny textil drogerie nábytek ================================== using System; using System.Collections.Generic; using System.Text; namespace simulace { public enum TypUdalosti { Start, Trpelivost, Obslouzen } public class Udalost { public int kdy; public Proces kdo; public TypUdalosti co; public Udalost(int kdy, Proces kdo, TypUdalosti co) { this.kdy = kdy; this.kdo = kdo; this.co = co; } } public class Kalendar { private List seznam; public Kalendar() { seznam = new List(); } public void Pridej(int kdy, Proces kdo, TypUdalosti co) { //Console.WriteLine("PLAN: {0} {1} {2}", kdy, kdo.ID, co); // pro hledani chyby: foreach (Udalost ud in seznam) if (ud.kdo == kdo) Console.WriteLine(""); seznam.Add(new Udalost(kdy, kdo, co)); } public void Odeber(Proces kdo, TypUdalosti co) { foreach (Udalost ud in seznam) { if ((ud.kdo == kdo) && (ud.co == co)) { seznam.Remove(ud); return; // odebiram jen jeden vyskyt! } } } public Udalost Prvni() { Udalost prvni = null; foreach (Udalost ud in seznam) if ((prvni == null) || (ud.kdy < prvni.kdy)) prvni = ud; seznam.Remove(prvni); return prvni; } public Udalost Vyber() { return Prvni(); } } public abstract class Proces { public static char[] mezery = { ' ' }; public int patro; public string ID; public abstract void Zpracuj(Udalost ud); public void log(string zprava) { //if (ID=="Dana") //if (ID=="elefant") if (this is Zakaznik) Console.WriteLine("{0}/{3} {1}: {2}", model.Cas, ID, zprava, patro); } protected Model model; } public class Oddeleni : Proces { private int rychlost; private List fronta; private bool obsluhuje; public Oddeleni(Model model, string popis) { this.model = model; string[] popisy = popis.Split(Proces.mezery, StringSplitOptions.RemoveEmptyEntries); this.ID = popisy[0]; this.patro = int.Parse(popisy[1]); if (this.patro > model.MaxPatro) model.MaxPatro = this.patro; this.rychlost = int.Parse(popisy[2]); obsluhuje = false; fronta = new List(); model.VsechnaOddeleni.Add(this); } public void ZaradDoFronty(Zakaznik zak) { fronta.Add(zak); log("do fronty " + zak.ID); if (obsluhuje) ; // nic else { obsluhuje = true; model.Naplanuj(model.Cas, this, TypUdalosti.Start); } } public void VyradZFronty(Zakaznik koho) { foreach (Zakaznik zak in fronta) if (zak == koho) { fronta.Remove(zak); return; } } public override void Zpracuj(Udalost ud) { switch (ud.co) { case TypUdalosti.Start: if (fronta.Count == 0) obsluhuje = false; // a dal neni naplanovana a probudi se tim, ze se nekdo zaradi do fronty else { Zakaznik zak = fronta[0]; fronta.RemoveAt(0); model.Odplanuj(zak, TypUdalosti.Trpelivost); model.Naplanuj(model.Cas + rychlost, zak, TypUdalosti.Obslouzen); model.Naplanuj(model.Cas + rychlost, this, TypUdalosti.Start); } break; } } } public enum SmeryJizdy { Nahoru, Dolu, Stoji } public class Vytah : Proces { private int kapacita; private int dobaNastupu; private int dobaVystupu; private int dobaPatro2Patro; static int[] ismery = { +1, -1, 0 }; // prevod (int) SmeryJizdy na smer private class Pasazer { public Proces kdo; public int kamJede; public Pasazer(Proces kdo, int kamJede) { this.kdo = kdo; this.kamJede = kamJede; } } private List[,] cekatele; // [patro,smer] private List naklad; // pasazeri ve vytahu private SmeryJizdy smer; private int kdyJsemMenilSmer; public void PridejDoFronty(int odkud, int kam, Proces kdo) { Pasazer pas = new Pasazer(kdo, kam); if (kam > odkud) cekatele[odkud, (int)SmeryJizdy.Nahoru].Add(pas); else cekatele[odkud, (int)SmeryJizdy.Dolu].Add(pas); // pripadne rozjet stojici vytah: if (smer == SmeryJizdy.Stoji) { model.Odplanuj(model.vytah, TypUdalosti.Start); // kdyby nahodou uz byl naplanovany model.Naplanuj(model.Cas, this, TypUdalosti.Start); } } public bool CekaNekdoVPatrechVeSmeruJizdy() { int ismer = ismery[(int)smer]; for (int pat = patro + ismer; (pat > 0) && (pat <= model.MaxPatro); pat += ismer) if ((cekatele[pat, (int)SmeryJizdy.Nahoru].Count > 0) || (cekatele[pat, (int)SmeryJizdy.Dolu].Count > 0)) { if (cekatele[pat, (int)SmeryJizdy.Nahoru].Count > 0) log("Nahoru ceka " + cekatele[pat, (int)SmeryJizdy.Nahoru][0].kdo.ID + " v patre " + pat + "/" + cekatele[pat, (int)SmeryJizdy.Nahoru][0].kdo.patro); if (cekatele[pat, (int)SmeryJizdy.Dolu].Count > 0) log("Dolu ceka " + cekatele[pat, (int)SmeryJizdy.Dolu][0].kdo.ID + " v patre " + pat + "/" + cekatele[pat, (int)SmeryJizdy.Dolu][0].kdo.patro); //log(" x "+cekatele[pat, (int)SmeryJizdy.Nahoru].Count+" x "+cekatele[pat, (int)SmeryJizdy.Dolu].Count); return true; } return false; } public Vytah(Model model, string popis) { this.model = model; string[] popisy = popis.Split(Proces.mezery, StringSplitOptions.RemoveEmptyEntries); this.ID = popisy[0]; this.kapacita = int.Parse(popisy[1]); this.dobaNastupu = int.Parse(popisy[2]); this.dobaVystupu = int.Parse(popisy[3]); this.dobaPatro2Patro = int.Parse(popisy[4]); this.patro = 0; this.smer = SmeryJizdy.Stoji; this.kdyJsemMenilSmer = -1; cekatele = new List[model.MaxPatro + 1, 2]; for (int i = 0; i < model.MaxPatro + 1; i++) { for (int j = 0; j < 2; j++) { cekatele[i, j] = new List(); } } naklad = new List(); } public override void Zpracuj(Udalost ud) { switch (ud.co) { case TypUdalosti.Start: // HACK pro cerstve probuzeny vytah: if (smer == SmeryJizdy.Stoji) // stoji, tedy nikoho neveze a nekdo ho prave probudil => nastavim jakykoliv smer a najde ho: smer = SmeryJizdy.Nahoru; // chce nekdo vystoupit? foreach (Pasazer pas in naklad) if (pas.kamJede == patro) // bude vystupovat: { naklad.Remove(pas); pas.kdo.patro = patro; model.Naplanuj(model.Cas + dobaVystupu, pas.kdo, TypUdalosti.Start); log("vystupuje " + pas.kdo.ID); model.Naplanuj(model.Cas + dobaVystupu, this, TypUdalosti.Start); return; // to je pro tuhle chvili vsechno } // muze a chce nekdo nastoupit? if (naklad.Count == kapacita) // i kdyby chtel nekdo nastupovat, nemuze; veze lidi => pokracuje: { // popojet: int ismer = ismery[(int)smer]; patro = patro + ismer; string spas = ""; foreach (Pasazer pas in naklad) spas += " " + pas.kdo.ID; log("odjizdim"); model.Naplanuj(model.Cas + dobaPatro2Patro, this, TypUdalosti.Start); return; // to je pro tuhle chvili vsechno } else // neni uplne plny { // chce nastoupit nekdo VE SMERU jizdy? if (cekatele[patro, (int)smer].Count > 0) { log("nastupuje " + cekatele[patro, (int)smer][0].kdo.ID); naklad.Add(cekatele[patro, (int)smer][0]); cekatele[patro, (int)smer].RemoveAt(0); model.Naplanuj(model.Cas + dobaNastupu, this, TypUdalosti.Start); return; // to je pro tuhle chvili vsechno } // ve smeru jizdy nikdo nenastupuje: if (naklad.Count > 0) // nikdo nenastupuje, vezu pasazery => pokracuju v jizde: { // popojet: int ismer = ismery[(int)smer]; patro = patro + ismer; string spas = ""; foreach (Pasazer pas in naklad) spas += " " + pas.kdo.ID; //log("nekoho vezu"); log("odjizdim: " + spas); model.Naplanuj(model.Cas + dobaPatro2Patro, this, TypUdalosti.Start); return; // to je pro tuhle chvili vsechno } // vytah je prazdny, pokud v dalsich patrech ve smeru jizdy uz nikdo neceka, muze zmenit smer nebo se zastavit: if (CekaNekdoVPatrechVeSmeruJizdy() == true) // pokracuje v jizde: { // popojet: int ismer = ismery[(int)smer]; patro = patro + ismer; //log("nekdo ceka"); log("odjizdim"); model.Naplanuj(model.Cas + dobaPatro2Patro, this, TypUdalosti.Start); return; // to je pro tuhle chvili vsechno } // ve smeru jizdy uz nikdo neceka => zmenit smer nebo zastavit: if (smer == SmeryJizdy.Nahoru) smer = SmeryJizdy.Dolu; else smer = SmeryJizdy.Nahoru; log("zmena smeru"); //chce nekdo nastoupit prave tady? if (kdyJsemMenilSmer != model.Cas) { kdyJsemMenilSmer = model.Cas; // podivat se, jestli nekdo nechce nastoupi opacnym smerem: model.Naplanuj(model.Cas, this, TypUdalosti.Start); return; } // uz jsem jednou smer menil a zase nikdo nenastoupil a nechce => zastavit log("zastavuje"); smer = SmeryJizdy.Stoji; return; // to je pro tuhle chvili vsechno } } } } public class Zakaznik : Proces { private int trpelivost; private int prichod; private List Nakupy; public Zakaznik(Model model, string popis) { this.model = model; string[] popisy = popis.Split(Proces.mezery, StringSplitOptions.RemoveEmptyEntries); this.ID = popisy[0]; this.prichod = int.Parse(popisy[1]); this.trpelivost = int.Parse(popisy[2]); Nakupy = new List(); for (int i = 3; i < popisy.Length; i++) { Nakupy.Add(popisy[i]); } this.patro = 0; Console.WriteLine("Init Zakaznik: {0}", ID); model.Naplanuj(prichod, this, TypUdalosti.Start); } public override void Zpracuj(Udalost ud) { switch (ud.co) { case TypUdalosti.Start: if (Nakupy.Count == 0) // ma nakoupeno { if (patro == 0) log("-------------- odchází"); // nic, konci else model.vytah.PridejDoFronty(patro, 0, this); } else { Oddeleni odd = OddeleniPodleJmena(Nakupy[0]); int pat = odd.patro; if (pat == patro) // to oddeleni je v patre, kde prave jsem { if (Nakupy.Count > 1) model.Naplanuj(model.Cas + trpelivost, this, TypUdalosti.Trpelivost); odd.ZaradDoFronty(this); } else model.vytah.PridejDoFronty(patro, pat, this); } break; case TypUdalosti.Obslouzen: log("Nakoupeno: " + Nakupy[0]); Nakupy.RemoveAt(0); // ...a budu hledat dalsi nakup -->> Start model.Naplanuj(model.Cas, this, TypUdalosti.Start); break; case TypUdalosti.Trpelivost: // vyradit z fronty: { Oddeleni odd = OddeleniPodleJmena(Nakupy[0]); odd.VyradZFronty(this); } // prehodit tenhle nakup na konec: string nesplneny = Nakupy[0]; Nakupy.RemoveAt(0); Nakupy.Add(nesplneny); // ...a budu hledat dalsi nakup -->> Start model.Naplanuj(model.Cas, this, TypUdalosti.Start); break; } } private Oddeleni OddeleniPodleJmena(string kamChci) { foreach (Oddeleni odd in model.VsechnaOddeleni) if (odd.ID == kamChci) return odd; return null; } } public class Model { public int Cas; public Vytah vytah; public List VsechnaOddeleni = new List(); public int MaxPatro; private Kalendar kalendar; public void Naplanuj(int kdy, Proces kdo, TypUdalosti co) { kalendar.Pridej(kdy, kdo, co); } public void Odplanuj(Proces kdo, TypUdalosti co) { kalendar.Odeber(kdo, co); } public void VytvorProcesy() { System.IO.StreamReader soubor = new System.IO.StreamReader(@"D:\Tom\data-obchod.txt", Encoding.GetEncoding(1250)); while (!soubor.EndOfStream) { string s = soubor.ReadLine(); if (s != "") { switch (s[0]) { case 'O': new Oddeleni(this, s.Substring(1)); break; case 'Z': new Zakaznik(this, s.Substring(1)); break; case 'V': vytah = new Vytah(this, s.Substring(1)); break; } } } soubor.Close(); } public int Vypocet() { Cas = 0; kalendar = new Kalendar(); VytvorProcesy(); Udalost ud; while ((ud = kalendar.Vyber()) != null) { //Console.WriteLine("{0} {1} {2}", ud.kdy, ud.kdo.ID, ud.co); Cas = ud.kdy; ud.kdo.Zpracuj(ud); } return Cas; } } class Program { static void Main(string[] args) { Model model = new Model(); Console.Write("{0} KONEC --------------------------------", model.Vypocet()); Console.ReadLine(); } } } ==================================== using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { enum TypUdalosti { PrijezdDoA, ZacniNakladat, JedAB, ZacniVykladat, JedBA } struct Udalost { public Auto Kdo; public int Kdy; public TypUdalosti Co; public Udalost(Auto Kdo, int Kdy, TypUdalosti Co) { this.Kdo = Kdo; this.Kdy = Kdy; this.Co = Co; } } class Model { static Kalendar kalendar; public static int Cas; public static int PisekVA, PisekVB; public static int VzdalenostAB; public static int KdyBudeVolnyNakladac; static int PocetAut = 1; public static void Naplanuj(Auto Kdo, int Kdy, TypUdalosti Co) { kalendar.Naplanuj(Kdo, Kdy, Co); } public static void VytvorAuta() { for (int i = 1; i <= PocetAut; i++) { new Auto("auto_"+i, 60, 10, 60, 5); } } public static int Vypocet(int PocetAut,int PisekVA, int VzdalenostAB) { kalendar = new Kalendar(); Cas = 0; Model.PisekVA = PisekVA; Model.PisekVB = 0; Model.KdyBudeVolnyNakladac = Cas; Model.VzdalenostAB = VzdalenostAB; Model.PocetAut = PocetAut; VytvorAuta(); int kolikPiskuPotrebujuVB = PisekVA; while (PisekVB < kolikPiskuPotrebujuVB) { Udalost U = kalendar.NejblizsiUdalost(); Cas = U.Kdy; //Console.WriteLine("{0}: {1} {2} {3} {4}", Cas, Model.PisekVA, Model.PisekVB, U.Co, U.Kdo.jmeno); U.Kdo.ZpracujUdalost(U.Co); } return Cas; } } class Auto { public string jmeno; int rychlost; int nosnost; int dobaNakladani, dobaVykladani; int kolikVeze; public Auto(string jmeno, int rychlost, int nosnost, int dobaNakladani, int dobaVykladani) { this.jmeno = jmeno; this.rychlost = rychlost; this.nosnost = nosnost; this.dobaNakladani = dobaNakladani; this.dobaVykladani = dobaVykladani; Model.Naplanuj(this, Model.Cas, TypUdalosti.PrijezdDoA); } public void ZpracujUdalost(TypUdalosti Co) { switch (Co) { case TypUdalosti.PrijezdDoA: int kdyZacnuNakladat; if (Model.KdyBudeVolnyNakladac > Model.Cas) kdyZacnuNakladat = Model.KdyBudeVolnyNakladac; else kdyZacnuNakladat = Model.Cas; Model.Naplanuj(this, kdyZacnuNakladat, TypUdalosti.ZacniNakladat); Model.KdyBudeVolnyNakladac = kdyZacnuNakladat + this.dobaNakladani; break; case TypUdalosti.ZacniNakladat: Model.Naplanuj(this, Model.Cas + this.dobaNakladani, TypUdalosti.JedAB); break; case TypUdalosti.JedAB: if (Model.PisekVA >= nosnost) kolikVeze = nosnost; else kolikVeze = Model.PisekVA; Model.PisekVA -= kolikVeze; int dobaJizdyAB = 60 * Model.VzdalenostAB / this.rychlost; Model.Naplanuj(this, Model.Cas + dobaJizdyAB, TypUdalosti.ZacniVykladat); break; case TypUdalosti.ZacniVykladat: Model.Naplanuj(this, Model.Cas + this.dobaVykladani, TypUdalosti.JedBA); break; case TypUdalosti.JedBA: Model.PisekVB += kolikVeze; int dobaJizdyBA = 60 * Model.VzdalenostAB / this.rychlost; Model.Naplanuj(this, Model.Cas + dobaJizdyBA, TypUdalosti.PrijezdDoA); break; default: break; } } } class Kalendar { const int MAX = 1000; Udalost[] pole = new Udalost[MAX]; int pocet = 0; public void Naplanuj(Auto Kdo, int Kdy, TypUdalosti Co) { pole[pocet] = new Udalost(Kdo, Kdy, Co); pocet++; } public Udalost NejblizsiUdalost() { int imin = 0; for (int i = 1; i < pocet; i++) { if (pole[i].Kdy < pole[imin].Kdy) imin = i; } Udalost prvni = pole[imin]; pole[imin] = pole[pocet - 1]; pocet--; return prvni; } } class Program { static void Main(string[] args) { for (int i = 1; i < 50; i++) { int doba = Model.Vypocet(i, 10000, 10000); Console.WriteLine("{0},{1}",i,doba); } } } }