Vereinsmeisterschaften  22aa7800eae54b428d40e835886cefe1fdefdfdf
This is a software that can be used to manage the internal competition of the swimming club Illertissen called "Vereinsmeisterschaften".
Loading...
Searching...
No Matches
RudolphTable.cs
1using System.Globalization;
2using System.Text.RegularExpressions;
3
5{
13 public class RudolphTable
14 {
15 #region Constants
16
17 public const string FEMALE_MARKER = "weiblich";
18 public const string MALE_MARKER = "männlich";
19 public const string AGE_MARKER = "Jahre";
20 public const string AGE_MARKER_ALTERNATIVE = "Altersklasse";
21 public const string OPEN_AGE_MARKER = "offen";
22 public const string END_PAGE_MARKER = "Klaus Rudolph";
23 public const string TIME_FORMAT_REGEX = @"\d{2}:\d{2},\d{2}";
24 public const string TIME_FORMAT_STRING = @"mm\:ss\,ff";
25 public const int NUMBER_TIME_COLUMNS_RUDOLPH_TABLE = 17;
26 public static readonly List<SwimmingStyles> SWIMMINGSTYLES_PER_TIME_COLUMN = new List<SwimmingStyles>()
27 {
28 SwimmingStyles.Freestyle,
29 SwimmingStyles.Freestyle,
30 SwimmingStyles.Freestyle,
31 SwimmingStyles.Freestyle,
32 SwimmingStyles.Freestyle,
33 SwimmingStyles.Freestyle,
34 SwimmingStyles.Breaststroke,
35 SwimmingStyles.Breaststroke,
36 SwimmingStyles.Breaststroke,
37 SwimmingStyles.Butterfly,
38 SwimmingStyles.Butterfly,
39 SwimmingStyles.Butterfly,
40 SwimmingStyles.Backstroke,
41 SwimmingStyles.Backstroke,
42 SwimmingStyles.Backstroke,
43 SwimmingStyles.Medley,
45 };
46 public static readonly List<ushort> DISTANCES_PER_TIME_COLUMN = new List<ushort>()
47 {
48 50,
49 100,
50 200,
51 400,
52 800,
53 1500,
54 50,
55 100,
56 200,
57 50,
58 100,
59 200,
60 50,
61 100,
62 200,
63 200,
64 400
65 };
66
67 #endregion
68
69 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
70
71 #region Properties
72
76 public List<RudolphTableEntry> Entries { get; private set; }
77
78 #endregion
79
80 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
81
82 #region Constructors
83
87 public RudolphTable()
88 {
89 }
90
95 public RudolphTable(string csvFile)
96 {
97 ParseFromCsv(csvFile);
98 }
99
100 #endregion
101
102 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
103
152 public void ParseFromCsv(string csvFile)
153 {
154 Entries = new List<RudolphTableEntry>();
155
156 using(StreamReader reader = new StreamReader(csvFile))
157 {
158 // Read the .csv content and split it to lines. Remove empty lines. Also remove " from the line entries.
159 string csvContent = reader.ReadToEnd();
160 List<string> csvLines = csvContent.Split("\n").Select(line => line.Replace("\"", "").Trim()).Where(line => !string.IsNullOrEmpty(line)).ToList();
161
162 RudolphTableEntry baseEntry = new RudolphTableEntry();
163 bool wasGenderOrAgeFound = false;
164 bool collectRudolphScoreLines = false;
165 string currentRudolphScoreTimesStr = "";
166
167 foreach (string line in csvLines)
168 {
169 // This is the line that contains the gender
170 if(line.Contains(FEMALE_MARKER) || line.Contains(MALE_MARKER))
171 {
172 baseEntry.Gender = line.Contains(FEMALE_MARKER) ? Genders.Female : Genders.Male;
173 wasGenderOrAgeFound = true;
174 }
175 // This is the line that contains the age
176 else if (line.Contains(AGE_MARKER) || line.Contains(AGE_MARKER_ALTERNATIVE))
177 {
178 string ageStr = "";
179 byte age = 0;
180 Match match = Regex.Match(line, $"(.*) {AGE_MARKER}");
181 Match matchAlternative = Regex.Match(line, $"{AGE_MARKER_ALTERNATIVE} (.*)");
182 if ((match.Success && match.Groups.Count >= 2) || (matchAlternative.Success && matchAlternative.Groups.Count >= 2))
183 {
184 ageStr = match.Success ? match.Groups[1].Value : matchAlternative.Groups[1].Value;
185 if(byte.TryParse(ageStr, out age))
186 {
187 baseEntry.Age = age;
188 wasGenderOrAgeFound = true;
189 }
190 }
191 }
192 // This is the line that contains the open age marker
193 else if (line.Contains(OPEN_AGE_MARKER))
194 {
195 baseEntry.Age = 0;
196 baseEntry.IsOpenAge = true;
197 wasGenderOrAgeFound = true;
198 }
199 // This is a line that contains the end page marker
200 else if(line.Contains(END_PAGE_MARKER))
201 {
202 baseEntry = new RudolphTableEntry() { Gender = baseEntry.Gender, RudolphScore = 0 }; // reuse last gender (if it's not contained on the page)
203 wasGenderOrAgeFound = false;
204 }
205 // This is a line that contains a rudolph score (only a single number between 1 and 20)
206 else if(line.Trim().Length <= 2 && wasGenderOrAgeFound)
207 {
208 byte score = 0;
209 if (byte.TryParse(line.Trim(), out score))
210 {
211 if(baseEntry.RudolphScore != score)
212 {
213 // start of block reached. Start collecting the time strings.
214 collectRudolphScoreLines = true;
215 baseEntry.RudolphScore = score;
216 }
217 else
218 {
219 // end of block reached. Parse the times.
220 collectRudolphScoreLines = false;
221 Entries.AddRange(parseEntriesFromRudolphScoreTimesStr(currentRudolphScoreTimesStr, baseEntry));
222 currentRudolphScoreTimesStr = "";
223 }
224 }
225 }
226 // This is a line that contains times for the current rudolph score
227 else if(collectRudolphScoreLines && wasGenderOrAgeFound)
228 {
229 currentRudolphScoreTimesStr += " " + line;
230 }
231 }
232 }
233 }
234
235 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
236
244 private static List<RudolphTableEntry> parseEntriesFromRudolphScoreTimesStr(string rudolphScoreTimesStr, RudolphTableEntry baseEntry)
245 {
246 List<RudolphTableEntry> rudolphScoreEntries = new List<RudolphTableEntry>();
247
248 MatchCollection timeMatches = Regex.Matches(rudolphScoreTimesStr, TIME_FORMAT_REGEX);
249 if (timeMatches.Count != NUMBER_TIME_COLUMNS_RUDOLPH_TABLE)
250 {
251 throw new Exception("Error while parsing rudolph table: line encountered that contains a wrong number of times.");
252 }
253 int timeColumnIndex = 0;
254 foreach (Match match in timeMatches)
255 {
256 RudolphTableEntry singleEntry = (RudolphTableEntry)baseEntry.Clone();
257 TimeSpan time;
258 if (TimeSpan.TryParseExact(match.Value, TIME_FORMAT_STRING, CultureInfo.InvariantCulture, out time))
259 {
260 singleEntry.Time = time;
261 singleEntry.SwimmingStyle = SWIMMINGSTYLES_PER_TIME_COLUMN[timeColumnIndex];
262 singleEntry.Distance = DISTANCES_PER_TIME_COLUMN[timeColumnIndex];
263 rudolphScoreEntries.Add(singleEntry);
264 }
265 timeColumnIndex++;
266 }
267
268 return rudolphScoreEntries;
269 }
270
271 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
272
285 public RudolphTableEntry GetEntryByParameters(Genders gender, byte age, SwimmingStyles swimmingStyle, ushort distance, byte rudolphScore)
286 {
287 List<RudolphTableEntry> entries = Entries.Where(e => e.Gender == gender && e.SwimmingStyle == swimmingStyle && e.Distance == distance && e.RudolphScore == rudolphScore).ToList();
288 if(entries == null || entries.Count == 0) { return null; }
289
290 byte maxAgeEntries = entries.Max(e => e.Age);
291 if (age > maxAgeEntries)
292 {
293 return entries.FirstOrDefault(e => e.IsOpenAge);
294 }
295 else
296 {
297 return entries.FirstOrDefault(e => e.Age == age);
298 }
299 }
300 }
301}
Class describing a single entry in the rudolph table (one single cell containing one time).
object Clone()
Create a new object that has the same property values than this one.
RudolphTable()
Empty Constructor for the RudolphTable.
static List< RudolphTableEntry > parseEntriesFromRudolphScoreTimesStr(string rudolphScoreTimesStr, RudolphTableEntry baseEntry)
Parse a string containing times to RudolphTableEntry objects.
RudolphTable(string csvFile)
Constructor for the RudolphTable that immediatelly parses the given table .csv.
List< RudolphTableEntry > Entries
List with all entries of the table parsed from the .csv.
RudolphTableEntry GetEntryByParameters(Genders gender, byte age, SwimmingStyles swimmingStyle, ushort distance, byte rudolphScore)
Try to get a specific RudolphTableEntry.
void ParseFromCsv(string csvFile)
Parse a .csv file to RudolphTableEntry objects.
SwimmingStyles
Available swimming styles.
Genders
Available genders for a person.
Definition Genders.cs:7