· 6 years ago · Oct 11, 2019, 05:06 PM
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.IO;
5using Newtonsoft.Json;
6
7namespace ParkingApp
8{
9 class ParkingManager
10 {
11 private List<ParkingSession> activeParkingSessions { get; set; }
12 private List<ParkingSession> completedParkingSessions { get; set; }
13 private List<Tariff> tariffTable { get; set; }
14 private int parkingCapacity;
15 private int last_ticket = 0;
16 private int freeLeavePeriod;
17
18 private const string _folderPath = "../../Data";
19 private const string ActiveSessionsFileName = "ActiveSessionsStorage.json";
20 private const string CompletedSessionsFileName = "CompletedSessionsStorage.json";
21 private const string TariffFileName = "TariffStorage.json";
22 private const string BasicInfoFileName = "BasicInfo.txt";
23
24 /* BASIC PART */
25 public void InitiliseComponents()
26 {
27 activeParkingSessions = new List<ParkingSession>();
28 completedParkingSessions = new List<ParkingSession>();
29 tariffTable = new List<Tariff>();
30 LoadTariffJSON();
31 LoadActiveSessionsJSON();
32 LoadCompletedSessionsJSON();
33 LoadBasicInfoTXT();
34 }
35
36 public ParkingSession EnterParking(string carPlateNumber)
37 {
38 Console.WriteLine(activeParkingSessions.Count);
39 Console.WriteLine(tariffTable.Count);
40 /* Check that there is a free parking place (by comparing the parking capacity
41 * with the number of active parking sessions). If there are no free places, return null */
42 if (activeParkingSessions.Count >= parkingCapacity)
43 {
44 Console.WriteLine("No available places");
45 return null;
46 }
47 /* Also check that there are no existing active sessions with the same car plate number,
48 * if such session exists, also return null*/
49 for (int l = 0; l < activeParkingSessions.Count; l++)
50 {
51 if (activeParkingSessions[l].CarPlateNumber == carPlateNumber)
52 {
53 return null;
54 }
55 }
56 /* Otherwise:
57 * Create a new Parking session, fill the following properties:
58 * EntryDt = current date time
59 * CarPlateNumber = carPlateNumber (from parameter)
60 * TicketNumber = unused parking ticket number = generate this programmatically
61 */
62 ParkingSession currentParkingSession = new ParkingSession();
63 currentParkingSession.CarPlateNumber = carPlateNumber;
64 currentParkingSession.TicketNumber = GenerateNumber();
65 currentParkingSession.EntryDt = DateTime.Now;
66 //* Add the newly created session to the list of active sessions
67 activeParkingSessions.Add(currentParkingSession);
68 /*
69 * Advanced task:
70 * Link the new parking session to an existing user by car plate number (if such user exists)
71 */
72 SaveActiveSessions();
73 return currentParkingSession;
74 }
75
76 private int GenerateNumber(){
77 last_ticket += 1;
78 SaveBasicInfo();
79 return last_ticket;
80 }
81
82 public void FillInTariffTable()
83 {
84 tariffTable = new List<Tariff>();
85 Tariff tariff_15 = new Tariff();
86 tariff_15.Minutes = 15;
87 tariff_15.Rate = 0;
88 tariffTable.Add(tariff_15);
89 freeLeavePeriod = tariff_15.Minutes;
90
91 for ( int k = 1; k <= 10; k++)
92 {
93 Tariff tariffUniversal = new Tariff();
94 tariffUniversal.Minutes = 60 * k;
95 tariffUniversal.Rate = 35 * k;
96 tariffTable.Add(tariffUniversal);
97 } /*optimizirovat vremya i dengi)*/
98 }
99
100 public ParkingSession FindSession(int ticketNumber){
101 for (int i = 0; i < activeParkingSessions.Count; i++)
102 {
103 if ( activeParkingSessions[i].TicketNumber == ticketNumber)
104 {
105 return activeParkingSessions[i];
106 }
107 }
108 return null;
109 }
110 public int FindElementOfList(List <ParkingSession> activeParkingSessions, int ticketNumber)
111 {
112 for (int m = 0; m < activeParkingSessions.Count; m++)
113 {
114 if (activeParkingSessions[m].TicketNumber == ticketNumber)
115 {
116 return m;
117 }
118 }
119 return -1;
120 }
121 public bool TryLeaveParkingWithTicket(int ticketNumber, out ParkingSession session)
122 {
123 session = FindSession(ticketNumber);
124 /*
125 * Check that the car leaves parking within the free leave period
126 * from the PaymentDt (or if there was no payment made, from the EntryDt)
127 * 1. If yes:
128 * 1.1 Complete the parking session by setting the ExitDt property
129 * 1.2 Move the session from the list of active sessions to the list of past sessions *
130 * 1.3 return true and the completed parking session object in the out parameter
131 *
132 * 2. Otherwise, return false, session = null
133 */
134 //???????????????????????REFACTOR LOGIC???????????????
135 DateTime entryDt = session.EntryDt;
136
137 if (session.PaymentDt != null)
138 {
139 DateTime paymentDt = session.PaymentDt ?? DateTime.Now;
140 TimeSpan dateRange = DateTime.Now - paymentDt;
141 int dateRangeMinutes = dateRange.Minutes;
142 if (dateRangeMinutes <= 15)
143 {
144 session.ExitDt = DateTime.Now;
145 int index = FindElementOfList(activeParkingSessions, ticketNumber);
146 activeParkingSessions.RemoveAt(index);
147 completedParkingSessions.Add(session);
148 SaveCompletedSessions();
149 return true;
150 }
151 else
152 {
153 session = null;
154 return false;
155
156 }
157 }
158 else
159 {
160 session = null;
161 return false;
162 }
163 }
164 public decimal GetRemainingCost(int ticketNumber)
165 {
166 ParkingSession session = FindSession(ticketNumber);
167
168 decimal previousPayments = 0;
169
170 previousPayments = session.TotalPayment ?? 0;
171
172 /* Return the amount to be paid for the parking*/
173 DateTime paymentDt = session.PaymentDt ?? DateTime.Now;
174 DateTime entryDt = session.EntryDt;
175 TimeSpan dataOnParking = paymentDt - entryDt;
176 int minutesOnParking = dataOnParking.Minutes;
177
178 foreach ( Tariff el in tariffTable)
179 {
180 if ( minutesOnParking <= el.Minutes)
181 {
182 return el.Rate - previousPayments;
183 }
184 }
185 return 350 - previousPayments;
186 /* If a payment had already been made but additional charge was then given
187 * because of a late exit, this method should return the amount
188 * that is yet to be paid (not the total charge)
189 */
190 }
191 public void PayForParking(int ticketNumber, decimal amount)
192 {
193 /*
194 * Save the payment details in the corresponding parking session
195 * Set PaymentDt to current date and time
196 *
197 * For simplicity we won't make any additional validation here and always
198 * assume that the parking charge is paid in full
199 */
200 ParkingSession session = FindSession(ticketNumber);
201 session.TotalPayment = amount;
202 session.PaymentDt = DateTime.Now;
203 SaveActiveSessions();
204 }
205
206 private void SaveActiveSessions()
207 {
208 var serialized = JsonConvert.SerializeObject(activeParkingSessions);
209 using (var sw = new StreamWriter(Path.Combine(_folderPath, ActiveSessionsFileName)))
210 {
211 sw.Write(serialized);
212 }
213 }
214
215 private void SaveCompletedSessions()
216 {
217 var serialized = JsonConvert.SerializeObject(completedParkingSessions);
218 using (var sw = new StreamWriter(Path.Combine(_folderPath, CompletedSessionsFileName)))
219 {
220 sw.Write(serialized);
221 }
222 }
223
224 private void SaveBasicInfo()
225 {
226 using (var sw = new StreamWriter(Path.Combine(_folderPath, BasicInfoFileName)))
227 {
228 sw.Write($"{parkingCapacity}, {last_ticket}");
229 }
230 }
231
232 public void SaveBasicFiles()
233 {
234 FillInTariffTable();
235 if (!Directory.Exists(_folderPath))
236 Directory.CreateDirectory(_folderPath);
237 var serialized = JsonConvert.SerializeObject(tariffTable);
238 using (var sw = new StreamWriter(Path.Combine(_folderPath, TariffFileName)))
239 {
240 sw.Write(serialized);
241 }
242 using (var sw = new StreamWriter(Path.Combine(_folderPath, ActiveSessionsFileName)))
243 {
244 sw.Write("[]");
245 }
246 using (var sw = new StreamWriter(Path.Combine(_folderPath, CompletedSessionsFileName)))
247 {
248 sw.Write("[]");
249 }
250 using (var sw = new StreamWriter(Path.Combine(_folderPath, BasicInfoFileName)))
251 {
252 sw.Write($"40,{last_ticket}");
253 }
254 }
255 private void LoadTariffJSON()
256 {
257 using (var sr = new StreamReader(Path.Combine(_folderPath, TariffFileName)))
258 {
259 var data = sr.ReadToEnd();
260 var deserialized = JsonConvert.DeserializeObject<List<Tariff>>(data);
261 tariffTable.AddRange(deserialized);
262 }
263 freeLeavePeriod = tariffTable[0].Minutes;
264 }
265
266 private void LoadActiveSessionsJSON()
267 {
268 using (var sr = new StreamReader(Path.Combine(_folderPath, ActiveSessionsFileName)))
269 {
270 var data = sr.ReadToEnd();
271 var deserialized = JsonConvert.DeserializeObject<List<ParkingSession>>(data);
272 activeParkingSessions.AddRange(deserialized);
273 }
274 }
275
276 private void LoadCompletedSessionsJSON()
277 {
278 using (var sr = new StreamReader(Path.Combine(_folderPath, CompletedSessionsFileName)))
279 {
280 var data = sr.ReadToEnd();
281 var deserialized = JsonConvert.DeserializeObject<List<ParkingSession>>(data);
282 completedParkingSessions.AddRange(deserialized);
283 }
284 }
285
286 private void LoadBasicInfoTXT()
287 {
288 using (var sr = new StreamReader(Path.Combine(_folderPath, BasicInfoFileName)))
289 {
290 var line = sr.ReadLine();
291 var parts = line.Split(',');
292 parkingCapacity = Convert.ToInt32(parts[0]);
293 last_ticket = Convert.ToInt32(parts[1]);
294 Console.WriteLine(parts[1]);
295 Console.WriteLine(last_ticket);
296 }
297 }
298
299 public void printTariff()
300 {
301 foreach (Tariff elem in tariffTable)
302 {
303 Console.WriteLine(elem.Minutes);
304 }
305 }
306 /*
307 public void SaveUserFavourites() {
308 using (var sw = new StreamWriter(GetUserFavouritesPath(_authorizedUser.Id))) {
309 using (var jsonWriter = new JsonTextWriter(sw)) {
310 var serializer = new JsonSerializer();
311 serializer.Serialize(jsonWriter, _authorizedUser.Favourites);
312 }
313 }
314 }
315 */
316 /* ADDITIONAL TASK 2 */
317 public bool TryLeaveParkingByCarPlateNumber(string carPlateNumber, out ParkingSession session)
318 {
319 /* There are 3 scenarios for this method:
320
321 1. The user has not made any payments but leaves the parking within the free leave period
322 from EntryDt:
323 1.1 Complete the parking session by setting the ExitDt property
324 1.2 Move the session from the list of active sessions to the list of past sessions *
325 1.3 return true and the completed parking session object in the out parameter
326
327 2. The user has already paid for the parking session (session.PaymentDt != null):
328 Check that the current time is within the free leave period from session.PaymentDt
329 2.1. If yes, complete the session in the same way as in the previous scenario
330 2.2. If no, return false, session = null
331
332 3. The user has not paid for the parking session:
333 3a) If the session has a connected user (see advanced task from the EnterParking method):
334 ExitDt = PaymentDt = current date time;
335 TotalPayment according to the tariff table:
336
337 IMPORTANT: before calculating the parking charge, subtract FreeLeavePeriod
338 from the total number of minutes passed since entry
339 i.e. if the registered visitor enters the parking at 10:05
340 and attempts to leave at 10:25, no charge should be made, otherwise it would be unfair
341 to loyal customers, because an ordinary printed ticket could be inserted in the payment
342 kiosk at 10:15 (no charge) and another 15 free minutes would be given (up to 10:30)
343
344 return the completed session in the out parameter and true in the main return value
345
346 3b) If there is no connected user, set session = null, return false (the visitor
347 has to insert the parking ticket and pay at the kiosk)
348 */
349 throw new NotImplementedException();
350 }
351 }
352}