ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/Qzhteln/trunk/TELTest/QuizGamemode.cs
Revision: 2
Committed: Wed Feb 11 13:07:01 2026 UTC (8 weeks, 4 days ago) by figdor32
File size: 8969 byte(s)
Log Message:
Initial check-in

File Contents

# Content
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using TELTest.Matchmaking;
7
8 namespace TELTest {
9 public abstract class QuizGamemode {
10 public static List<QuizGamemode> Registry { get; } = new List<QuizGamemode>() {
11 new Gamemodes.Classic(),
12 new Gamemodes.ClassicMP(),
13 new Gamemodes.Kbmio(),
14 new Gamemodes.Pisania(),
15 new Gamemodes.Comments(),
16 //new Gamemodes.Turns()
17 };
18 protected QuizGamemode() { }
19 protected QuizGamemode(QuizContainer container, BaseQuizContext context) {
20 this.Quiz = container;
21 this.Context = context;
22 }
23 public QuizContainer Quiz { get; protected set; }
24 public BaseQuizContext Context { get; protected set; }
25 public abstract QuizGamemode CreateInstance(QuizContainer quiz, BaseQuizContext context);
26 public QuizGamemode CreateCheckInstance(QuizContainer quiz, BaseQuizContext context) {
27 var inst = CreateInstance(quiz, context);
28 if (inst.GetType() != this.GetType()) throw new InvalidOperationException("Sanity check: QuizGamemode.CreateInstance should return the current type, it returned " + inst.GetType() + " instead of " + this.GetType() + ".");
29 return inst;
30 }
31 public abstract string Name { get; }
32 public abstract string SystemName { get; }
33 public abstract string Description { get; }
34 protected const string SYSTEMNAME_WHITELIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
35 public abstract Task Begin();
36 public void JoinExistingLobby(Lobby lobby) {
37 m_JoinMe = lobby;
38 }
39 private Lobby m_JoinMe = null;
40 protected bool ValidateSystemName() {
41 if (string.IsNullOrWhiteSpace(Name)) return false;
42 for (int i = 0; i < SystemName.Length; i++) {
43 if (!SYSTEMNAME_WHITELIST.Contains(SystemName[i])) return false;
44 }
45 return true;
46 }
47 public virtual async Task<Lobby> CreateJoinLobbyStandard() {
48 await GUIUtilities.AskUsernameIfNeeded(Context.Handler, Context.Stream);
49 Lobby lobby = null;
50 if (m_JoinMe == null) {
51 lobby = MatchmakingStuff.RequestNew(Quiz, this);
52 lobby.Players.Add(this.Context.Handler);
53 await GUIUtilities.LobbySettings(this.Context.Handler, this.Context.Stream, lobby);
54 } else {
55 lobby = m_JoinMe;
56 lobby.Players.Add(this.Context.Handler);
57 m_JoinMe = null;
58 }
59 bool aw = await GUIUtilities.LobbyAwait(this.Context.Handler, this.Context.Stream, lobby);
60 if (!aw) {
61 lobby.Players.Remove(Context.Handler);
62 return null;
63 }
64 //MakePlayersUnready(lobby);
65 return lobby;
66 }
67 const string SPINNER = "|/-\\";
68 public virtual async Task WaitForPlayersReady(Lobby lobby, bool clearScreen = false) {
69 //lobby.Players.Where(x => x == Context.Handler).First().PlayerReady = true;
70 Context.Handler.PlayerReady = true;
71 int spinstage = 0;
72 if (clearScreen) {
73 await Clear();
74 await WriteLine();
75 }
76 while (true) {
77 bool allready = true;
78 for (int i = 0; i < lobby.Players.Count; i++) {
79 allready &= lobby.Players[i].PlayerReady;
80 }
81
82 await Write("\r " + SPINNER[spinstage] + " Czekanie na reszte graczy... " + SPINNER[spinstage] + " ");
83 await Task.Delay(150);
84 spinstage++;
85 if (spinstage >= SPINNER.Length) spinstage = 0;
86 if (allready) break;
87 }
88 await WriteLine();
89 await Task.Delay(300);
90 }
91 public void MakePlayersUnready(Lobby lobby) {
92 for (int i = 0; i < lobby.Players.Count; i++) {
93 lobby.Players[i].PlayerReady = false;
94 }
95 }
96 public virtual async Task DoScoreSubmission(int score, bool _reserved = false) {
97 if (!ValidateSystemName()) throw new InvalidOperationException("The system name of the gamemode is null, empty, exclusively whitespace, or contains invalid characters. Valid characters are \"" + SYSTEMNAME_WHITELIST + "\" (without quotes).");
98 Context.Handler.Flush(Context.Stream);
99 var scoreboard = Scoreboard.Of(Quiz.Guid + "_" + SystemName);
100 await Clear();
101 string nic = "";
102 if (!string.IsNullOrWhiteSpace(Context.Handler.PlayerName)) {
103 if (await Context.Handler.Choice(Context.Stream, new[] { 'Y', 'N' }, "Zapisac wynik?", def: 'Y') == 'Y') {
104 nic = Context.Handler.PlayerName;
105 scoreboard.Add(new Scoreboard.ScoreboardEntry(nic, score));
106 }
107
108 } else {
109 await Write(Localization.UI["SAVESCORE"] + " ");
110 nic = await Context.Handler.Read(Context.Stream, new ReadConfiguration() {
111 Echo = true,
112 Terminator = '\n',
113 FlushAfterReading = true,
114 MaxLength = 30,
115 Whitelist = SYSTEMNAME_WHITELIST
116 });
117 nic = nic.TrimEnd('\r', '\n').Trim();
118 if (!string.IsNullOrWhiteSpace(nic)) {
119 scoreboard.Add(new Scoreboard.ScoreboardEntry(nic, score));
120 Context.Handler.PlayerName = nic;
121 }
122 }
123 await Clear();
124 StringBuilder sb = new StringBuilder();
125 var high = scoreboard.Highscore();
126 bool hadScore = false;
127 for (Int32 i = 0; i < high.Length; i++) {
128 Scoreboard.ScoreboardEntry item = high[i];
129 bool current = item.Name == nic;
130 hadScore |= current;
131 sb.AppendLineRN(((i + 1).ToString().PadLeft(2) + ". " + (current? "-> " : " ") + item.Name).PadRight(38) + " " + item.Value);
132 }
133
134 if (!string.IsNullOrWhiteSpace(nic) && !hadScore) {
135 for (Int32 i = 0; i < scoreboard.Entries.Count; i++) {
136 var item = scoreboard.Entries[i];
137 if (item.Name == nic) {
138 sb.AppendLineRN();
139 bool current = true;
140 sb.AppendLineRN((i.ToString().PadLeft(2) + ". " + (current ? "->" : "") + item.Name).PadRight(38) + " " + item.Value);
141 }
142 }
143 }
144 sb.AppendLineRN();
145 await WriteLine(sb.ToString());
146 await Pause();
147 }
148 public Task EndMP(Lobby lobby) {
149 lobby.Players.Remove(Context.Handler);
150 if (lobby.Players.Count == 0 && !lobby.AnnouncePublic) {
151 lock (MatchmakingStuff.AllLobbies)
152 MatchmakingStuff.AllLobbies.Remove(lobby);
153 }
154 Context.Handler.PlayerReady = false;
155 return Task.FromResult(true);
156 }
157 public Task Flush() {
158 Context.Handler.Flush(Context.Stream);
159 return Task<bool>.FromResult(true);
160 }
161 public async Task Clear() {
162 await Context.Handler.TryClear(Context.Stream);
163 }
164 public async Task Pause() {
165 await Write(Localization.UI["ANYKEYCONTINUE"]);
166 await ReadKey(false);
167 await Flush();
168 await WriteLine();
169 }
170 public async Task WriteLine() => await WriteLine("");
171 public async Task WriteLine(object format, params object[] args) {
172 await Write(format + "\r\n", args);
173 }
174 public async Task Write(object format, params object[] args) {
175 await Context.Handler.WriteASCII(Context.Stream, string.Format(format.ToString(), args));
176 }
177 public async Task<string> ReadLine() => await ReadLine(true);
178 public async Task<string> ReadLine(bool echo) {
179 string rl = await Context.Handler.Read(Context.Stream, '\n', echo);
180 return rl.TrimEnd('\r', '\n');
181 }
182 public async Task<char> ReadUppercaseKey() {
183 char c = char.ToUpper(await ReadKey(false));
184 await Write(c);
185 return c;
186 }
187 public async Task<char> ReadKey() => await ReadKey(true);
188 public async Task<char> ReadKey(bool echo) {
189 return await Context.Handler.ReadChar(Context.Stream, echo);
190 }
191
192 }
193 }