using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using TELTest.Matchmaking; namespace TELTest { class NormalConnectionHandler : ConnectionHandler { public override async Task HandleMe(NetworkStream stream) { //await HandleTerminalSetup(stream); //await DoQuizNew(stream); await QuizExplorer(stream); //await DoQuizNewest(stream); } protected async Task QuizExplorer(NetworkStream stream) { int selx = 1; int sely = 0; TooLazyToAddWhile: string[] publicq = new string[QuizListing.CachePublic.Count]; QuizEntry[] qe = new QuizEntry[QuizListing.CachePublic.Count]; lock (QuizListing.Entries) { for (Int32 i = 0; i < QuizListing.CachePublic.Count; i++) { QuizEntry item = QuizListing.CachePublic[i]; publicq[i] = item.Name; qe[i] = item; } } PlayerReady = false; var cd = Path.Combine(".", "Quizzes", "Quizhouse_poor"); var cdn = Path.Combine(".", "Quizzes", "New"); string[] dirqhp = Directory.GetFileSystemEntries(cd, "*.jp2"); for (int i = 0; i < dirqhp.Length; i++) { dirqhp[i] = "FILE:" + dirqhp[i]; } string[] dirneu = Directory.GetFileSystemEntries(cdn, "*.xml"); for (int i = 0; i < dirneu.Length; i++) { dirneu[i] = "FILE:" + dirneu[i]; } string[] labels = new[] { "Klasycznym", "Menu", "Nowymi" }; string[][] menu = new string[3][]; //List ls = new List(); //for (int i = 0; i < 30; i++) { // ls.Add(Utilities.RandomString()); //} menu[0] = dirqhp; menu[1] = new[] { /* 0 */ "Dolacz do lobby", /* 1 */ "Publiczne lobby", //* 2 */ "Matchmaking", /* 2 */ "Stworz quiz", /* 3 */ "Zmien nick (" + (PlayerName == null? "Brak" : PlayerName)+ ")", /* 4 */ "Otworz prywatny quiz...", /* 5 */ "Wyjdz", }; menu[2] = publicq; var res = await GUIUtilities.Create2DMenu(this, stream, menu, labels, null, defaultx: selx, defaulty: sely); int xsel = res.Item1; int ysel = res.Item2; selx = xsel; sely = ysel; string sp = menu[xsel][ysel]; if (xsel == 1) { switch (ysel) { case 0: await JoinLobby(this, stream); break; case 1: await LobbyBrowser(stream); break; case 2: QuizCreator creator = new QuizCreator(); await creator.Handle(this, stream); break; case 3: await GUIUtilities.AskUsernameIfNeeded(this, stream, true); break; case 4: await OpenPrivate(stream); break; case 5: return; default: break; } } if (xsel == 2) { var itm = qe[ysel]; QuizContainer qc = QuizDraftManager.GetDraft(itm.ID); await ProcOpenQuiz(stream, qc); } if (sp.StartsWith("FILE:")) { sp = sp.Substring(5).Trim(); QuizContainer qc = null; switch (Path.GetExtension(sp).ToUpper()) { case ".JP2": string content = System.IO.File.ReadAllText(sp); qc = QuizContainer.FromQuizhouse_poor(content); string meta = sp + ".meta"; if (!System.IO.File.Exists(meta)) { System.IO.File.AppendAllText(meta, Guid.NewGuid() + "\r\n"); } Guid g = Guid.Parse(System.IO.File.ReadAllLines(meta)[0].Trim()); qc.Guid = g; break; case ".XML": qc = QuizContainer.FromXml(System.IO.File.ReadAllText(sp)); break; default: throw new InvalidOperationException("Not a filename - " + sp); } await ProcOpenQuiz(stream, qc); } goto TooLazyToAddWhile; } public async Task OpenPrivate(NetworkStream stream) { await WriteASCII(stream, "Wpisz ID quizu aby go otworzyc."); bool invalid = false; while (true) { await TryClear(stream); await WriteASCII(stream, "Wpisz identyfikator quizu aby go otworzyc.\r\n\r\n"); if (invalid) await WriteASCII(stream, "Wpisano nieprawidlowy identyfikator.\r\n"); await WriteASCII(stream, "Identyfikator: "); string nam = await Read(stream, new ReadConfiguration() { Terminator = '\r', Echo = true, MaxLength = 20, Whitelist = Utilities.ALPHANUMERIC, FlushAfterReading = true, }); string li = nam.Trim(); bool lockObtained = false; try { Monitor.Enter(QuizListing.Entries); lockObtained = true; for (int i = 0; i < QuizListing.Entries.Count; i++) { var itm = QuizListing.Entries[i]; if (itm.ID == li) { await TryClear(stream); await WriteASCII(stream, "Czekaj...."); if (!QuizDraftManager.Contains(itm.ID)) { Monitor.Exit(QuizListing.Entries); lockObtained = false; await TryClear(stream); await WriteASCII(stream, "Wystapil nieoczekiwany blad - znaleziono wpis quizu ale nie znaleziono danych."); await ReadChar(stream); Flush(stream); return; } Monitor.Exit(QuizListing.Entries); lockObtained = false; await ProcOpenQuiz(stream, QuizDraftManager.GetDraft(itm.ID)); return; } } } finally { if (lockObtained) Monitor.Exit(QuizListing.Entries); } invalid = true; if (string.IsNullOrWhiteSpace(nam)) break; } } public async Task ProcOpenQuiz(NetworkStream stream, QuizContainer container) { BaseQuizContext bq = new BaseQuizContext(this, stream, container); await bq.Handle(); } public async Task LobbyBrowser(NetworkStream stream) { Lobby[] lobbies = MatchmakingStuff.GetPublic().ToArray(); int lastsel = 1; while (true) { string[] names = lobbies.Select(x => x.Name + ", " + x.Subject.Author + " - " + x.Subject.Title + " [" + x.Identifier + (x.PlayerLimit == -1 ? "" : (", " + x.Players.Count + "/" + x.PlayerLimit)) + "]").ToArray(); string[][] menu = new string[1][]; menu[0] = new string[names.Length + 2]; menu[0][0] = "Powrot..."; menu[0][1] = "Odswiez"; Array.Copy(names, 0, menu[0], 2, names.Length); var res = (await GUIUtilities.Create2DMenu(this, stream, menu, new[] { "Publiczne lobby" }, defaulty: lastsel)).Item2; if (res == 0) { return; } else if (res == 1) { lobbies = MatchmakingStuff.GetPublic().ToArray(); names = lobbies.Select(x => x.Name + "[" + x.Identifier + "]").ToArray(); } else { var sel = res - 2; await JoinLobbyProcess(stream, lobbies[sel]); } lastsel = res; } } public async Task JoinLobby(ConnectionHandler handler, NetworkStream stream) { //if (!string.IsNullOrWhiteSpace(handler.PlayerName)) return; bool invalid = false; while (true) { await handler.TryClear(stream); await handler.WriteASCII(stream, "Wpisz identyfikator lobby (5-7 znakow).\r\n\r\n"); if (invalid) await handler.WriteASCII(stream, "Wpisano nieprawidlowy identyfikator.\r\n"); await handler.WriteASCII(stream, "Identyfikator: "); string nam = await handler.Read(stream, new ReadConfiguration() { Terminator = '\r', Echo = true, MaxLength = 10, Whitelist = Utilities.ALPHANUMERIC, FlushAfterReading = true, }); string li = nam.Trim(); for (int i = 0; i < MatchmakingStuff.AllLobbies.Count; i++) { var itm = MatchmakingStuff.AllLobbies[i]; if (itm.Identifier == li) { await TryClear(stream); await WriteASCII(stream, "Czekaj...."); await JoinLobbyProcess(stream, itm); return; } } invalid = true; if (string.IsNullOrWhiteSpace(nam)) break; } } public async Task JoinLobbyProcess(NetworkStream stream, Lobby lobby) { QuizGamemode qg = lobby.Gamemode; if (lobby.PlayerLimit != -1 && lobby.Players.Count >= lobby.PlayerLimit) { await TryClear(stream); await WriteASCII(stream, "Lobby jest pelne.\r\n\r\nNacisnij dowolny klawisz aby kontynuowac..."); await ReadChar(stream); Flush(stream); return; } if (!string.IsNullOrWhiteSpace(lobby.Password)) { await TryClear(stream); await WriteASCII(stream, "Haslo: "); var rc = ReadConfiguration.Default; rc.EchoPasswordChars = true; string pwd = await Read(stream, rc); if (!string.IsNullOrWhiteSpace(pwd)) { if (lobby.Password != pwd) return; } else { return; } } var ctx = new BaseQuizContext(this, stream, lobby.Subject); var game = qg.CreateCheckInstance(lobby.Subject, ctx); game.JoinExistingLobby(lobby); await game.Begin(); } protected async Task DoQuizNewest(NetworkStream stream) { string qc = File.ReadAllText("Quizzes\\Quizhouse_poor\\quiz.jp2"); QuizContainer quiz = QuizContainer.FromQuizhouse_poor(qc); BaseQuizContext bq = new BaseQuizContext(this, stream, quiz); await bq.Handle(); } protected async Task HandleTerminalSetup(NetworkStream stream) { await TryClear(stream); char c = await Choice(stream, new[] { '4', '8', '1' }, "Czy to terminal z [4]0, [8]0, czy [1]20 kolumn?", def: '1'); switch (c) { default: case '4': Columns = 40; break; case '8': Columns = 80; break; case '1': Columns = 120; break; } Flush(stream); await TryClear(stream); await WriteASCII(stream, "The bar below should fill the width of the console. If not, resize your console, or reconnect and try again.\r\n"); await WriteBar(stream); } protected async Task DoQuizNew(NetworkStream stream) { var ct = File.ReadAllText("quiz.jp2"); var quiz = QuizContainer.FromQuizhouse_poor(ct); async Task CW(object ln = null) => await WriteASCII(stream, ln + "\r\n"); async Task RK() { char c = await ReadChar(stream); Flush(stream); return c; } int wynik = 0; await TryClear(stream); await CW("Tytul quizu: " + quiz.Title); await CW("Autor quizu: " + quiz.Author); await CW("Dowolny klawisz aby rozpoczac...."); await RK(); for (int i = 0; i < quiz.Questions.Length; i++) { await TryClear(stream); var itm = quiz.Questions[i]; await CW((i + 1) + ". " + itm.Content + "\r\n"); char correctAnswer = 'A'; for (int j = 0; j < itm.Answers.Length; j++) { await CW(Utilities.NumberToLetter(j) + ") " + itm.Answers[j].Content); if (itm.Answers[j].Correct) correctAnswer = Utilities.NumberToLetter(j)[0]; } await WriteASCII(stream, "Twoja odpowiedz: "); char c = await ReadChar(stream, false); await CW(char.ToUpper(c)); await CW(); if (char.ToUpper(c) == correctAnswer) { wynik++; await CW("Dobrze! Zdobywasz punkt!"); } else { await CW("Zle! Prawidlowa odpowiedz to: " + correctAnswer); } await CW("Dowolny klawisz aby kontynuowac...."); await RK(); } await TryClear(stream); await CW("Twoj wynik: " + wynik + "/" + quiz.Questions.Length); await CW("Dowolny klawisz aby kontynuowac...."); await RK(); } protected async Task DoQuiz(NetworkStream stream) { bool twrd = false; await TryClear(stream); // await WriteBar(stream); //await WriteASCII(stream, "Tryb T W A R D O R D Z E N wcisnij \"T\", klasyczny wcisnij inny dowolny klawisz.\r\n"); await WriteASCII(stream, "Tryb trudny wcisnij \"T\", klasyczny wcisnij inny dowolny klawisz.\r\n"); //await WriteBar(stream); twrd = char.ToUpper(await ReadChar(stream)) == 'T'; Flush(stream); Stream s = File.OpenRead("quiz.jp2"); TextReader tr = new StreamReader(s); int wynik = 0; bool twrdis = false; int twr = 1; string qti = tr.ReadLine(); string qau = tr.ReadLine(); #region process for (int i = 0; i < 5; ++i) { await TryClear(stream); await WriteASCII(stream, (i == 0 ? "Tytul quizu: " : "") + qti + "\r\n"); if (i == 0) await WriteASCII(stream, "Autor quizu: " + qau + "\r\n"); //await WriteBar(stream); await WriteASCII(stream, "\r\n\r\n"); await WriteASCII(stream, (i + 1) + ". " + tr.ReadLine() + "\r\n\r\n"); await WriteASCII(stream, "a) " + tr.ReadLine() + "\r\n"); await WriteASCII(stream, "b) " + tr.ReadLine() + "\r\n"); await WriteASCII(stream, "c) " + tr.ReadLine() + "\r\n"); await WriteASCII(stream, "d) " + tr.ReadLine() + "\r\n"); char op = tr.ReadLine()[0]; await WriteASCII(stream, "\r\n? "); char rc = await ReadChar(stream, true); await WriteASCII(stream, "\r\n"); if (char.ToUpper(op) == Char.ToUpper(rc)) { await WriteASCII(stream, "Dobrze! Zdobywasz punkt!\r\n"); wynik++; } else { if (twrd) { if (!twrdis) { //await WriteASCII(stream, "Tryb T W A R D O R D Z E N oznacza, ze niepoprawne odpowiedzi dodatkowo usuwaja twoje punkty. Kazda kolejna niepoprawna odpowiedz usuwa dwa razy wiecej punktow od poprzedniej, na przyklad pierwsza usuwa 1, druga 2 a trzecia 4.\r\n"); await WriteASCII(stream, "Tryb trudny: kazda kolejna niepoprawna odpowiedz usuwa dwa razy wiecej punktow od poprzedniej.\r\n"); twrdis = true; } await WriteASCII(stream, "Zle! Tracisz " + (twr == 1 ? "" : twr + "") + "punkt" + ( twr == 1 ? "" : twr <= 5 ? "y" : "ow" // max 31, 32 znowu sie odmienia na "-y" ale akurat -31 to max ) + ".\r\n"); wynik -= twr; twr <<= 1; } else { await WriteASCII(stream, "Zle! Poprawna odpowiedz to: " + op + "\r\n"); } } Flush(stream); if (wynik < 0) await WriteASCII(stream, "Uwaga: Twoj wynik jest ujemny! Masz [" + wynik + "] punktow.\r\n\r\n"); await WriteASCII(stream, "Nacisnij dowolny klawisz aby kontynuowac...."); await ReadChar(stream, true); Flush(stream); } #endregion await TryClear(stream); await WriteASCII(stream, "Twoj wynik: " + wynik + "/5\r\n\r\nUdostepnic?\r\n- Jezeli tak, wpisz nick (max 30 znakow) i wcisnij enter.\r\n- Jezeli nie, nic nie wpisuj i wcisnij enter.\r\n\r\n"); string nic = await Prompt(stream, "? ", new ReadConfiguration() { MaxLength = 30, Whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_", Echo = true, Terminator = '\n' }); if (!string.IsNullOrWhiteSpace(nic)) { File.AppendAllText("Hiscore.txt", nic + ":" + wynik + "\n"); } Tuple[] hs = Array.ConvertAll(File.ReadAllLines("Hiscore.txt"), (x) => { string nm = x.Split(':')[0]; string trz = x.Split(':')[1]; int ioi; if (!int.TryParse(trz, out ioi)) { ioi = -123456789; } return new Tuple(nm, ioi); }); StringBuilder sb = new StringBuilder(); hs = hs.OrderBy(x => -x.Item2).ToArray(); bool ht = false; const int MAX_HISCORE = 15; for (int i = 0; i < (hs.Length < MAX_HISCORE? hs.Length : MAX_HISCORE); i++) { var item = hs[i]; bool tho = item.Item1 == nic; ht |= tho; sb.Append(((i + 1) + ". " + (tho? "-> " : "") + item.Item1).PadRight(38) + " " + item.Item2 + "\r\n"); } if (!ht && !string.IsNullOrWhiteSpace(nic)) { int ord = 0; for (int i = 0; i < hs.Length; i++) { if (hs[i].Item1 == nic) { ord = i; break; } } sb.Append((ord + ". -> " + nic).PadRight(38) + " " + wynik + "\r\n"); } await TryClear(stream); //await WriteBar(stream); await WriteASCII(stream, "============= WYSOKI WYNIK: =============\r\n" + sb.ToString() + "\r\n"); //await WriteBar(stream); await WriteASCII(stream, "\r\n"); await WriteASCII(stream, "Nacisnij klawisz aby sie rozlaczyc."); await ReadChar(stream, true); Flush(stream); } } }