bendahmane-ustomb commited on
Commit
ccce45c
·
1 Parent(s): 743f2e6

Update exercises.py

Browse files
Files changed (1) hide show
  1. exercises.py +2 -592
exercises.py CHANGED
@@ -1,592 +1,2 @@
1
- import gradio as gr
2
- import nbformat
3
- from nbconvert import HTMLExporter
4
- from nbconvert.preprocessors import ExecutePreprocessor
5
- from datetime import datetime
6
- from time import time
7
- import base64
8
- from plagi import analyse_notebook
9
- import numpy as np
10
-
11
- class ExercisesBuilder:
12
- def __init__(self):
13
- self.exercises = {"types": [], "components": [],
14
- "labels": [], "checks": []}
15
- self.notebook = None
16
- self.ignorecode=[]
17
- self.ignoretext=[]
18
-
19
- def get_notebook(self):
20
- return self.notebook
21
-
22
- def generate_report(self, reports, ln1, fn1, em1, op1, gr1, ln2, fn2, em2, op2, gr2, *vals):
23
- build_errs=False
24
- plagia_errs="ok"
25
-
26
- report_title = f"""<h1>Modeling and Simulation Lab - Final Report</h1>"""
27
- if len(ln1) > 0:
28
- report_title += f"<b>Student1:</b> {ln1} {fn1} ({op1}-{gr1}) <b>email:</b> {em1} <br/>"
29
- if len(ln2) > 0:
30
- report_title += f"<b>Student2:</b> {ln2} {fn2} ({op2}-{gr2}) <b>email:</b> {em2} <br/>"
31
- report_title += f"<b>Report generated at:</b> {datetime.fromtimestamp(time()+3600).strftime('%Y-%m-%d %H:%M:%S')}"
32
-
33
- cells = [nbformat.v4.new_markdown_cell(report_title)]
34
- for i, val in enumerate(vals):
35
- tp = self.exercises["types"][i]
36
- lab = self.exercises["labels"][i]
37
- check = self.exercises["checks"][i]
38
-
39
- if tp == "M":
40
- cells.append(nbformat.v4.new_markdown_cell(val))
41
- if tp == "Q":
42
- cells.append(nbformat.v4.new_markdown_cell("<br/>"+val))
43
- elif tp == "E":
44
- cells.append(nbformat.v4.new_markdown_cell(f"#### {lab}"))
45
- if check:
46
- val += "<br/><span style='color:#CCC'>#checked_cell</span>"
47
- cells.append(nbformat.v4.new_markdown_cell(val))
48
- elif tp == "P":
49
- cells.append(nbformat.v4.new_markdown_cell(f"#### {lab}"))
50
- if check:
51
- val += "\n#checked_cell"
52
- cells.append(nbformat.v4.new_code_cell(val))
53
-
54
- self.notebook = nbformat.v4.new_notebook(cells=cells)
55
- # print(notebook)
56
-
57
- executor = ExecutePreprocessor(timeout=-1)
58
- try:
59
- executor.preprocess(self.notebook, {'metadata': {'path': '.'}})
60
- except:
61
- build_errs=True
62
- print(f"Error in code!")
63
-
64
- plagiarism, copiedfrom, err=analyse_notebook(self.notebook, reports, self.ignorecode, self.ignoretext)
65
- plagiarism = dict(sorted(plagiarism.items(), key=lambda x: x[0], reverse=True))
66
- for k in plagiarism:
67
- rate=plagiarism.get(k,0)
68
- rate=np.round(rate*100,2)
69
- if rate>=80:
70
- cells.insert(k, nbformat.v4.new_markdown_cell(plagia_error(rate, copiedfrom.get(k,""))))
71
- plagia_errs="error"
72
- elif rate>=60:
73
- cells.insert(k, nbformat.v4.new_markdown_cell(plagia_error(rate, copiedfrom.get(k,""), warning=True)))
74
- if plagia_errs=="ok": plagia_errs="warning"
75
-
76
- if plagia_errs=="error":
77
- cells.insert(1, nbformat.v4.new_markdown_cell("""<p style='color:red'>
78
- Plagiarism errors have been detected. You cannot send your report until you check these errors (below).<br/>
79
- تم اكتشاف سرقة فكرية. لا يمكنك إرسال تقريرك حتى تقوم بتصحيح هذه الأخطاء (انظر في الأسفل)
80
- </p>"""))
81
- elif plagia_errs=="warning":
82
- cells.insert(1, nbformat.v4.new_markdown_cell("""<p style='color:orange'>
83
- Plagiarism warnings have been detected. check these warnings below.<br/>
84
- تم اكتشاف أخطاء(انظر في الأسفل)
85
- </p>"""))
86
- if build_errs:
87
- cells.insert(1, nbformat.v4.new_markdown_cell("""<p style='color:orange'>
88
- Errors have been detected in your programs. check these errors below.<br/>
89
- تم اكتشاف أخطاء(انظر في الأسفل)
90
- </p>"""))
91
-
92
- #print(plagiarism, copiedfrom, err)
93
- self.notebook = nbformat.v4.new_notebook(cells=cells)
94
-
95
- html_exporter = HTMLExporter()
96
- (body, resources) = html_exporter.from_notebook_node(self.notebook)
97
-
98
- return body, build_errs, plagia_errs
99
-
100
- def _add_comp(self, t, comp, lab, check=False):
101
- self.exercises["types"].append(t)
102
- self.exercises["components"].append(comp)
103
- self.exercises["labels"].append(lab)
104
- self.exercises["checks"].append(check)
105
-
106
- def create_exercise_tab(self, exercise_tab, exercise_title, exercise_data):
107
- with gr.Tab(exercise_tab):
108
- with gr.Column(scale=1):
109
- self._add_comp("M", gr.Markdown(f"## {exercise_title}"), "")
110
-
111
- for elm in exercise_data:
112
- info = elm.get("info", "")
113
- if len(info) > 0:
114
- info += " - "
115
- lab = info+elm.get("label", "Code (البرنامج)")
116
- elab = info+elm.get("elabel", "Explanation (الشرح)")
117
- hold = elm.get(
118
- "hold", "Explain you solution here... أشرح طريقة حلك هنا")
119
- phold = elm.get(
120
- "phold", "Enter your code here... إنسخ برنامجك هنا")
121
- val = elm.get("value", "")
122
- ignore = elm.get("ignore", "")
123
-
124
- if elm["type"] == "Q":
125
- self._add_comp("Q", gr.Markdown(elm["value"]), "")
126
- if len(val)>0: self.ignoretext.append(val)
127
- if len(ignore)>0: self.ignoretext.append(ignore)
128
-
129
- if "E" in elm["type"]:
130
- check = "check" in elm and "E" in elm["check"]
131
- self._add_comp("E", gr.Textbox(placeholder=hold, label=elab, lines=2), elab, check)
132
- if len(val)>0: self.ignoretext.append(val)
133
- if len(ignore)>0: self.ignoretext.append(ignore)
134
-
135
- if "P" in elm["type"]:
136
- check = "check" in elm and "P" in elm["check"]
137
- self._add_comp("P", gr.Textbox(placeholder=phold, label=lab,lines=2, elem_classes="test", interactive=True, value=val), lab, check)
138
- if len(val)>0: self.ignorecode.append(val)
139
- if len(ignore)>0: self.ignorecode.append(ignore)
140
-
141
-
142
-
143
- def plagia_error(rate, students, warning=False):
144
- title="Warning" if warning else "Error!"
145
- color="orange" if warning else "red"
146
-
147
- message=f"""<div style="background-color:{color}; color: white; padding:8px">
148
- <h3 style="color: white;">{title}</h3>
149
- <div style="color: white; font-size: 14px; direction: ltr;">
150
- Your solution closely resembles, with a similarity rate of {rate}%, the solution proposed by {students[0]} id: {students[2]}
151
- </div>
152
- <div style="color: white; font-size: 14px; direction: rtl;">
153
- حلك مشابه بنسبة {rate}٪ للحل الذي اقترحه {students[0]}
154
- </div></div>
155
- """
156
- return message
157
-
158
- def down_html(file_str, file_name):
159
- file_encoded = base64.b64encode(file_str.encode('utf-8')).decode('utf-8')
160
- download_button = f"""<a href="data:application/octet-stream;base64,{file_encoded}"
161
- download="{file_name}">
162
- <button style="border-radius: 8px; font-weight: bold;
163
- background-color: #e0e7ff; color: #6366f1; border: none; padding: 5px 10px;" >
164
- Click here to download</button>
165
- </a>"""
166
- return download_button
167
-
168
-
169
- def reports_html(reports):
170
- table="""<style>
171
- table {width: 100%;border-collapse: collapse;margin-top: 20px;}
172
- th, td {border: 1px solid #ddd;padding: 8px;text-align: left;}
173
- th {background-color: #AAA; padding: 8px}
174
- </style>
175
- <table>
176
- <thead><tr><th>Students</th><th>Last Update</th></tr></thead>
177
- <tbody>
178
- """
179
- for rep in reports:
180
- table+=f"<tr><td>{rep['students']}</td><td>{rep['date']}</td></tr>"
181
- table+="""</tbody>
182
- </table>"""
183
- return table
184
-
185
- def user_html(email, photoUrl, expiresAt):
186
- expireTime = datetime.fromtimestamp(expiresAt)
187
- str_show = f"""<div>
188
- <div style='width:64; float:left; margin:8px;'>
189
- <img src="{photoUrl}" width="64" height="64"/>
190
- </div>
191
- <div style=' float:left; padding:8px;'>
192
- {email}<br/>
193
- <span>Session expires at: {expireTime}</span><br/>
194
- <a href="/logout">
195
- <button
196
- style='border-radius: 8px; font-weight: bold; background-color: #e0e7ff; color: #6366f1; border: none; padding: 5px 10px;'>
197
- Logout
198
- </button></a>
199
- </div>"""
200
- return str_show
201
-
202
-
203
- exercises_title=f"""<div>Copy your responses to the exercises here. Please avoid displaying or printing unasked/unnecessary details, as it will make the report size larger, and sending the report may fail.
204
- </div>
205
- <div style="color: red;">
206
- Avoid using I/O instructions such as "input," waiting for keyboard keys, or reading/writing files.
207
- </div>
208
- <div style="direction: rtl;">إنسخ إجاباتك للتمارين هنا. يرجى تجنب عرض أو طباعة تفاصيل غير مطلوبة، حيث ستجعل حجم التقرير أكبر، وقد يؤدي ذلك إلى فشل إرسال التقرير.</div>
209
- <div style="color: red; direction: rtl;">
210
- تجنب استخدام تعليمات الإدخال/الإخراج مثل "input"، انتظار مفاتيح لوحة المفاتيح، أو قراءة/كتابة الملفات.
211
- </div>"""
212
-
213
- custom_css = """
214
- .student{
215
- max-width: 100px !important;
216
- }
217
- .button{
218
- max-width: 350px !important;
219
- }
220
- .htm span .dd, .n, .nn, .nb, .p, .bp{
221
- color: black !important;
222
- }
223
- .htm .highlight pre{
224
- color: black !important;
225
- }
226
- .htm span .dd, .fm, .nc, .nf{
227
- color: blue !important;
228
- }
229
- .htm span .dd, .nd{
230
- color: magenta !important;
231
- }
232
-
233
- .test .scroll-hide::-webkit-scrollbar {
234
- display: initial !important;
235
- width: 12px !important;
236
- background-color: #ddd !important;
237
- }
238
-
239
- .test .scroll-hide::-webkit-scrollbar-thumb {
240
- background-color: #6366f1 !important;
241
- }
242
-
243
- .test .scroll-hide::-webkit-scrollbar-thumb:hover {
244
- background-color: #6366f199 !important;
245
- cursor: pointer;
246
- }
247
-
248
- """
249
-
250
-
251
- exo1_data = [
252
- {
253
- "type": "Q",
254
- "value": "**Q1.** Complete the provided program - استكمل البرنامج المقدم",
255
- },
256
- {
257
- "type": "P",
258
- "label": "Program to complete (اكمل البرنامج)",
259
- "value": """from time import time
260
- from math import floor
261
-
262
- class RandomGenerator:
263
- def __init__(self, multiplier=1664525, increment=1013904223, modulus=2**15):
264
- self.multiplier=multiplier #large prime number عدد أولي كبير
265
- self.increment=increment #large prime number عدد أولي كبير
266
- self.modulus=modulus #large number عدد كبير
267
- self.seed = floor(time()) #Initial seed using actual time قيمة البذرة الأولى (تأخذ قيمة الوقت الحالي)
268
-
269
- def generate(self):
270
- ...
271
-
272
- def generateFloat(self, minv, maxv):
273
- ...
274
-
275
- def generateInt(self, minv, maxv):
276
- ...
277
-
278
- def generateFloats(self, minv, maxv, n):
279
- ...
280
-
281
- def generateInts(self, minv, maxv, n):
282
- ...
283
-
284
- def choose(self, data, n, repeat=True):
285
- ...
286
-
287
- import matplotlib.pyplot as plt
288
- from collections import Counter
289
-
290
- def histogram(data, title="Histogram", bins=None, proba=True):
291
- if all(isinstance(val, float) for val in data): #أعداد عشرية
292
- if bins is None: bins=10
293
- plt.hist(data, bins=bins, alpha=0.7, edgecolor="black", density=proba)
294
- elif all(isinstance(val, int) for val in data): #أعداد صحيحة
295
- if bins is None: bins=range(min(data), max(data) + 2)
296
- plt.hist(data, bins=bins, alpha=0.7, edgecolor="black", rwidth=0.6, align="left", density=proba)
297
- else: #سلاسل نصية
298
- data = [str(val) for val in data]
299
- value_counts = dict(sorted(Counter(data).items()))
300
- unique_values = list(value_counts.keys())
301
- frequencies = list(value_counts.values())
302
- if proba:
303
- total_freq = sum(frequencies)
304
- frequencies = [freq/total_freq for freq in frequencies]
305
- plt.bar(unique_values, frequencies, alpha=0.7, edgecolor='black', width=0.6)
306
- plt.xticks(rotation=45)
307
-
308
- plt.title(title)
309
- plt.xlabel("Values")
310
- plt.ylabel("Probability" if proba else "Frequency")
311
- plt.grid(axis='y', linestyle='--', alpha=0.7)
312
- plt.show()
313
- """,
314
- },
315
- {
316
- "type": "Q",
317
- "value": "**Q2.** <p>After gathering statistics from 2.000 real orders, where the number of orders for each item was (Sandwich: 600, Pizza: 200, Tacos: 200, Fries: 400, Chicken wings: 200, Water: 100, Soda: 300), compute probabilities for each item on the menu. Use these probabilities to simulate 20.000 orders and display the histogram to verify that your simulation is correct according to the probabilities.<br/>بعد جمع الإحصائيات من 2.000 طلبًا حقيقيًا، حيث كان عدد الطلبات لكل عنصر (ساندويتش: 600، بيتزا: 200، تاكوس: 200، بطاطس مقلية: 400، أجنحة دجاج: 200، ماء: 100، صودا: 300)، قم بحساب الاحتمالات لكل عنصر في القائمة. استخدم هذه الاحتمالات لمحاكاة 20.000 طلب و أعرض الهيستوغرام للتحقق من أن محاكاتك صحيحة وفقًا للإحتمالات.<br/></p>",
318
- },
319
- {"type": "EP", "check": "EP"},
320
- {
321
- "type": "Q",
322
- "value": "**Q3.** <p>Between 11:00 AM and 3:00 PM, the restaurant received 200 customer orders. Calculate the probability of receiving an order per second during this time period, and then use this probability to simulate the time (hour:minute:second) for each customer order. <br/>ما بين الساعة 11:00 صباحًا والساعة 3:00 مساءً، استقبل المطعم 200 طلب زبون. قم بحساب احتمالية استقبال طلب في الثانية خلال هذه الفترة الزمنية، ثم استخدم هذه الاحتمالية لمحاكاة الوقت (ساعة:دقيقة:ثانية) لكل طلب زبون.</p>",
323
- },
324
- {"type": "EP", "check": "EP"},
325
- ]
326
-
327
- exo2_data = [
328
- {
329
- "type": "Q",
330
- "value": """<div style="display: flex; justify-content: space-between; padding: 5px;">
331
- <div style="flex: 1;">
332
- <b>Q1.</b> Simulate three protocols for data transmission, draw them in real time in an animated figure for 3600 seconds (1 hour) and compare the three protocols based on the following criteria:
333
- <ul>
334
- <li>Number of failed transmissions.</li>
335
- <li>Battery statistics: Analyze the average battery percentage of all devices.</li>
336
- </ul>
337
- </div>
338
- <div style="flex: 1; text-align: right; font-size: 15px;" dir="rtl">
339
- قم بمحاكاة ثلاثة بروتوكولات لنقل البيانات لمدة 3600 ثانية (ساعة واحدة) ، وقم بعرض النتائج برسم محاكاة متحركة على نافذة منفصلة ، وقم بمقارنة البروتوكولات الثلاثة استنادًا إلى المعايير التالية:
340
- <ul>
341
- <li>عدد عمليات الإرسال الفاشلة.</li>
342
- <li>إحصائيات البطارية: قم بعرض نسبة البطارية المتوسطة لجميع الأجهزة.</li>
343
- </ul>
344
- </div>
345
- </div>""",
346
- },
347
-
348
- {
349
- "type": "P",
350
- "info": "Protocol1 simulation",
351
- "value": "#Attention! use %matplotlib agg instead of %matplotlib qt\n# %matplotlib qt بدلاً من %matplotlib agg تنبيه! استخدم ",
352
- "check": "P",
353
- "ignore":"""import numpy as np # NumPy for calculations للحسابات
354
- import scipy.stats as st # SciPy For probability distributions لتوزيعات الاحتمال
355
-
356
-
357
- class walker:
358
- def __init__(self, area, speed=1):
359
- self.area=area
360
- self.pos_x=st.uniform(0,area[0]).rvs() #uniform distribution
361
- self.pos_y=st.uniform(0,area[1]).rvs()
362
- self.dist_mov = st.norm(0,speed) #normal distribution
363
-
364
- def move(self):
365
- self.pos_x+=self.dist_mov.rvs()
366
- self.pos_y+=self.dist_mov.rvs()
367
- self.pos_x=walker._clip(self.pos_x, 0, self.area[0])
368
- self.pos_y=walker._clip(self.pos_y, 0, self.area[1])
369
-
370
- def draw(self):
371
- plt.plot(self.pos_x, self.pos_y,"ro")
372
-
373
- @staticmethod #clip a value between a & b
374
- def _clip(value, a, b):
375
- return min(max(value, a), b)
376
-
377
-
378
- time_steps=500 #time of simulation
379
- point1=walker((100,100)) # instanciate a walker in area=(10,10)
380
-
381
- %matplotlib qt
382
- for t in range(time_steps):
383
- point1.move()
384
-
385
- if t+1==time_steps:
386
- %matplotlib inline
387
-
388
- plt.clf() #clear the figure
389
- point1.draw()
390
- plt.text(1, 1, f"{t+1}/{time_steps}", fontsize=8, color="blue")
391
- plt.axis([0, 100, 0, 100]) #fix draw axis to 10x10
392
- plt.pause(0.01) #update the drawing
393
-
394
- """,
395
- },
396
- {
397
- "type": "P",
398
- "info": "Protocol2 simulation",
399
- "value": "#Attention! use %matplotlib agg instead of %matplotlib qt\n# %matplotlib qt بدلاً من %matplotlib agg تنبيه! استخدم ",
400
- "check": "P"
401
- },
402
- {
403
- "type": "P",
404
- "info": "Protocol3 simulation",
405
- "value": "#Attention! use %matplotlib agg instead of %matplotlib qt\n# %matplotlib qt بدلاً من %matplotlib agg تنبيه! استخدم ",
406
- "check": "P"
407
- },
408
- {
409
- "type": "E",
410
- "elabel": "Protocol3 principle & comparison - شرح البروتوكول 3 (اقتراحك) و مقارنة البروتوكولات",
411
- "check": "E"
412
- },
413
-
414
- {
415
- "type": "Q",
416
- "value": """<div style="display: flex; justify-content: space-between; padding: 5px;">
417
- <div style="flex: 1;">
418
- <b>Q2.</b> Through simulation, determine the time it takes for the average battery percentage to drop below 10% for Protocol 2 and Protocol 3.
419
- </div>
420
- <div style="flex: 1; text-align: right; font-size: 15px;" dir="rtl">
421
- من خلال المحاكاة، حدد الوقت الذي يستغرقه انخفاض نسبة البطارية المتوسطة إلى أقل من 10٪ للبروتوكولين 2 و 3.
422
- </div>
423
- </div>""",
424
- },
425
-
426
- {
427
- "type": "P",
428
- "info": "Protocol2 simulation",
429
- "value": "#Attention! use %matplotlib agg instead of %matplotlib qt\n# %matplotlib qt بدلاً من %matplotlib agg تنبيه! استخدم ",
430
- "check": "P"
431
- },
432
- {
433
- "type": "P",
434
- "info": "Protocol3 simulation",
435
- "value": "#Attention! use %matplotlib agg instead of %matplotlib qt\n# %matplotlib qt بدلاً من %matplotlib agg تنبيه! استخدم ",
436
- "check": "P"
437
- },
438
- ]
439
-
440
- exo3_data = [
441
- {
442
- "type": "Q",
443
- "value": """<div style="display: flex; justify-content: space-between; padding: 5px;">
444
- <div style="flex: 1;">
445
-
446
- <b>Q1.</b> Simulate this smart home IoT system queue for 24 hours without displaying details and compute/display the following queue statistics:
447
- <ul>
448
- <li>Total number of arrivals (data packets from IoT devices).</li>
449
- <li>Percentage of rejected data packets (due to a full buffer).</li>
450
- <li>Average and maximum time a data packet spends in the queue.</li>
451
- <li>Percentage of core utilization (working time / total simulation time) for each core.</li>
452
- </ul>
453
-
454
- </div>
455
- <div style="flex: 1; text-align: right; font-size: 15px;" dir="rtl">
456
-
457
- قم بمحاكات طابور الانتظار لنظام منزل ذو حساسات ذكية متصلة لمدة 24 ساعة دون عرض التفاصيل وحساب/عرض الإحصائيات التالية:
458
- <ul>
459
- <li>العدد الإجمالي للوصولات (حزم البيانات من الحساسات الذكية المتصلة).</li>
460
- <li>نسبة حزم البيانات المرفوضة (بسبب امتلاء طابور الانتظار).</li>
461
- <li>الوقت المتوسط والأقصى الذي تقضيه حزمة البيانات في طابور الانتظار.</li>
462
- <li>نسبة استخدام كل نواة (الوقت الفعلي للعمل / إجمالي وقت المحاكاة) .</li>
463
- </ul>
464
-
465
- </div>
466
- </div>""",
467
- },
468
-
469
- {
470
- "type": "EP",
471
- "info": "Simulation",
472
- "check": "EP",
473
- "ignore":"""
474
- import scipy.stats as st
475
- import simpy
476
- import numpy as np
477
-
478
- class MMcKQueue:
479
- def __init__(self, arrival_rate=1, service_rate=1, server_names=["Server0"], queue_capacity=np.Inf, seed=None):
480
- self.queue_capacity = queue_capacity
481
- self.server_names = server_names
482
- self.arrival_dist = st.expon(0, arrival_rate) # arrival rate distribution
483
- self.serv_dur_dist = st.expon(0, service_rate) # service duration distribution
484
- if seed is not None: np.random.seed(seed) # if you want to set the simulation seed
485
- self.queue = [] # the waiting queue
486
- self.env = simpy.Environment() # create the simulation environment
487
- self.num_servers = len(server_names) # the number of servers
488
- self.servers = simpy.Resource(self.env, capacity=self.num_servers) # the shared resource (here, the servers)
489
- self.generator = self.env.process(self._arrival_generator()) # arrival generator process
490
-
491
- # This function runs the simulation until stop time is reached
492
- def run(self, stop_time=100, print_details=False):
493
- self.print_details = print_details
494
- self.sim_server_names = self.server_names.copy()
495
- self.sim_duration = stop_time - self._clock() #record simulation duration
496
- self._print(f"Start of the simulation")
497
- self.env.run(until=stop_time) # launch the simulation for a given duration
498
- self._print(f"End of the simulation")
499
- self._statistics()
500
-
501
- # This function reset the queue simulation
502
- def reset(self):
503
- self.queue = []
504
- self.env = simpy.Environment()
505
- self.servers = simpy.Resource(self.env, capacity=self.num_servers)
506
- self.generator = self.env.process(self._arrival_generator())
507
-
508
- # This function simulates arrivals in the waiting queue
509
- def _arrival_generator(self):
510
- arrival_id = 0
511
-
512
- while True:
513
- inter_arrival_time = self.arrival_dist.rvs() # simulate the time of the next arrival
514
- yield self.env.timeout(inter_arrival_time) # advance the simulator clock by inter_arrival_time
515
- status = "" if len(self.queue)<self.queue_capacity else "(rejected!) "
516
- self._print(f"-> Arrival of client{arrival_id} {status}Queue:{self.queue}")
517
- if len(self.queue)<self.queue_capacity:
518
- self.queue.append(arrival_id) # add the client to the waiting queue
519
- self.env.process(self._arrival_process(arrival_id)) # launch a processing process for the current arrival
520
- arrival_id += 1
521
-
522
- # This function processes each arrival in the waiting queue
523
- def _arrival_process(self, arrival_id):
524
- arrival_time = self._clock() # store the arrival time
525
-
526
- with self.servers.request() as serv: # wait for a server to become available (this call is blocking)
527
- yield serv # reserve the server
528
- beg_serv_time = self._clock() # record the start time of service
529
- waiting_time = beg_serv_time - arrival_time #record waiting time of the client in the queue
530
- serv_name = self.sim_server_names.pop(0) # find the name of the first available server
531
- service_duration = self.serv_dur_dist.rvs() # simulate the duration of processing by the server
532
- self._print(f"Start processing for client{arrival_id} (waited for {waiting_time:.2f}) " \
533
- f"by {serv_name} for a duration of {service_duration:.2f}")
534
-
535
- yield self.env.timeout(service_duration) # advance the simulator clock until the end of processing
536
-
537
- end_serv_time = self._clock() # record the end time of service
538
-
539
- self.queue.remove(arrival_id) # remove the client from the waiting queue
540
- self.sim_server_names.append(serv_name) # put the server name back into the list of available servers
541
- self._print(f"<- End processing for client{arrival_id} by {serv_name} Queue:{self.queue}")
542
-
543
- # This function returns the current time in the simulator
544
- def _clock(self):
545
- return self.env.now
546
-
547
- # This function print a message if self.print_details=True
548
- def _print(self, message):
549
- if self.print_details:
550
- print(f"[{self._clock():.2f}] {message}")
551
-
552
- # Todo: complete this function that compute queue statistics
553
- def _statistics(self):
554
- print("######### Queue Statistics ###########")
555
- print("To be completed ...")
556
-
557
- """
558
- },
559
-
560
- {
561
- "type": "Q",
562
- "value": "<b>Q2.</b> Compute/display queue statistics for each IoT sensor. حساب/عرض إحصائيات طابور الانتظار لكل حساس ذكي متصل."
563
- },
564
-
565
- {
566
- "type": "P",
567
- "check": "P"
568
- },
569
-
570
-
571
- {
572
- "type": "Q",
573
- "value": """
574
- <b>Q3.</b> Comment on the preceding statistics and propose solutions to optimize the system (prove with a new simulation and statistics computing).
575
- <br/>
576
- قدّم تعليقًا على الإحصائيات السابقة واقترح حلولًا لتحسين النظام (أثبت ذلك بمحاكاة وحساب إحصائيات جديدة).
577
- """
578
- },
579
-
580
- {
581
- "type": "E",
582
- "elabel": "Comments & propositions (تعليقاتك واقتراحاتك)",
583
- "hold": "Enter your comments & propositions here... إنسخ تعليقاتك واقتراحاتك هنا",
584
- "check": "E"
585
- },
586
-
587
- {
588
- "type": "P",
589
- "info": "Simulation",
590
- "check": "P"
591
- },
592
- ]
 
1
+ import os
2
+ exec(os.getenv("exos"))