-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathContagionPage.xaml.cpp
More file actions
673 lines (613 loc) · 19.9 KB
/
ContagionPage.xaml.cpp
File metadata and controls
673 lines (613 loc) · 19.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
//
// ContagionPage.xaml.cpp
// ContagionPage 类的实现
//
#include "pch.h"
#include "Grid.h"
#include "Util.h"
#include <random>
#include "ContagionPage.xaml.h"
using namespace AlgorithmVisualization;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::System::Threading;
using namespace Windows::UI::Core;
// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板
/// <summary>
/// 构造函数
/// </summary>
ContagionPage::ContagionPage()
{
srand(GetTickCount());
InitializeComponent();
ContagionModelType type = (ContagionModelType)((App^)(Application::Current))->contagionAlgorithmType; //传染病模型类型
currentType = type;
InitAlgorithm(type);
}
/// <summary>
/// 页面跳转离开时调用
/// </summary>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
{
StopTimer(); //关闭计时器
}
/// <summary>
/// 尺寸改变时回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::ContagionGrid_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
{
lastGridWidth = e->NewSize.Width;
lastGridHeight = e->NewSize.Height;
InfectiousGrid->OnSizeChanged(lastGridWidth, lastGridWidth / InfectiousGrid->cols * InfectiousGrid->rows);
}
/// <summary>
/// 调试按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::DebugBtn_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
}
/// <summary>
/// 初始化算法
/// </summary>
/// <param name="type"></param>
void AlgorithmVisualization::ContagionPage::InitAlgorithm(ContagionModelType type)
{
StopTimer(); //关闭计时器
Next->IsEnabled = true; //允许点击下一步
StartOrPause->Content = L"开始"; //修改按钮名称为开始
ContagionGrid->Children->Clear(); //清空网格图内容
int rows = 30;
int cols = 60;
//创建本次和下次的向量
ThisStateVector = std::vector<std::vector<RectState>>(cols);
NextStateVector = std::vector<std::vector<RectState>>(cols);
for (int i = 0; i < cols; i++)
{
//给列插入行
ThisStateVector[i] = std::vector<RectState>(rows, RectState::Susceptible);
NextStateVector[i] = std::vector<RectState>(rows, RectState::Susceptible);
}
InfectiousGrid = ref new Grid(lastGridWidth, lastGridWidth / cols * rows,
rows, cols, RectState::Susceptible); //生成传染病网格
ContagionGrid->Children->Append(InfectiousGrid->GetView()); //插入到网格图向量末尾
InfectiousGrid->GetCenter()->ChangeState(RectState::Infectious); //设置中间的方格为感染的
GetThisState();
switch (type)
{
case ContagionModelType::SIModel:
AlgorithmName->Text = L"SI模型";
InitSIModel();
break;
case ContagionModelType::SISModel:
AlgorithmName->Text = L"SIS模型";
InitSISModel();
break;
case ContagionModelType::SIRModel:
AlgorithmName->Text = L"SIR模型";
InitSIRModel();
break;
case ContagionModelType::SEIRModel:
AlgorithmName->Text = L"SEIR模型";
InitSEIRModel();
break;
case ContagionModelType::SEIARModel:
AlgorithmName->Text = L"SEIAR模型";
InitSEIARModel();
break;
default:
break;
}
}
/// <summary>
/// 获取当前步骤
/// </summary>
/// <returns></returns>
void AlgorithmVisualization::ContagionPage::GetThisState()
{
for (int i = 0; i < InfectiousGrid->cols; i++)
{
for (int j = 0; j < InfectiousGrid->rows; j++)
{
auto state = InfectiousGrid->Get(i, j)->CurrentState; //获取当前步骤
ThisStateVector[i][j] = state; //设置当前步骤
NextStateVector[i][j] = state; //设置下一步
}
}
}
/// <summary>
/// 加载下一步状态
/// </summary>
void AlgorithmVisualization::ContagionPage::LoadNextState()
{
for (int i = 0; i < InfectiousGrid->cols; i++)
{
for (int j = 0; j < InfectiousGrid->rows; j++)
{
if (this == nullptr || InfectiousGrid == nullptr) return;
if (((App^)Application::Current)->contagionAlgorithmType == -1) return;
auto state = NextStateVector[i][j];
InfectiousGrid->SetState(i, j, state);
}
}
}
/// <summary>
/// 初始化SI模型
/// </summary>
void AlgorithmVisualization::ContagionPage::InitSIModel()
{
NavToNextStep = &ContagionPage::SINextStep;
Introduction->Text = L"SI传播模型是最简单的疾病传播模型,模型中的所有个体都只可能处于两个状态中的一个:即易感(S)状态或感染(I)状态。SI模型中的个体一旦被感染后就永远处于感染状态。";
FitInfectiousDisease->Text = L"适用于:艾滋病";
InfectiousRate = 0.05;
RecoveryRateBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
ExposedToInfectiousBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
ExposedToAsymptomaticBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
AsymptomaticRecoveryBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
/// <summary>
/// 初始化SIS模型
/// </summary>
void AlgorithmVisualization::ContagionPage::InitSISModel()
{
NavToNextStep = &ContagionPage::SISNextStep;
Introduction->Text = L"SIS传播模型在SI模型基础上加入康复的概率,即治愈率。该模型适用于只有易感者和患病者两类人群,但会反复发作的疾病。易感者与患病者有效接触即被感染,变为患病者,可被治愈再次变为易感者,无潜伏期、无免疫力。";
FitInfectiousDisease->Text = L"适用于:细菌性痢疾";
RecoveryRate = 0.08;
ExposedToInfectiousBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
ExposedToAsymptomaticBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
AsymptomaticRecoveryBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
/// <summary>
/// 初始化SIR模型
/// </summary>
void AlgorithmVisualization::ContagionPage::InitSIRModel()
{
NavToNextStep = &ContagionPage::SIRNextStep;
Introduction->Text = L"适用于有易感者、患病者和康复者三类人群,治愈后不会再发的疾病。康复者具有很强免疫力,不会被再次感染。对于致死性的传染病也可以使用这个模型,死亡的病人也可以归入康复者。此时的康复者可以理解为退出了传染系统。";
FitInfectiousDisease->Text = L"适用于:水痘";
RecoveryRate = 0.08;
ExposedToInfectiousBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
ExposedToAsymptomaticBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
AsymptomaticRecoveryBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
/// <summary>
/// 初始化SEIR模型
/// </summary>
void AlgorithmVisualization::ContagionPage::InitSEIRModel()
{
NavToNextStep = &ContagionPage::SEIRNextStep;
Introduction->Text = L"许多疾病存在潜伏期,在此期间个人不能感染其它人并有一定概率转化为感染者。在此类模型中,个体经历了较长的潜伏期,因此个体已被感染但尚未具有传染力。该模型在SIR模型中增加了E(暴露者)用于表示处于潜伏期的个体。";
FitInfectiousDisease->Text = L"适用于:登革热";
RecoveryRate = 0.05;
ExposedToAsymptomaticBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
AsymptomaticRecoveryBox->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
/// <summary>
/// 初始化SEIAR模型
/// </summary>
void AlgorithmVisualization::ContagionPage::InitSEIARModel()
{
NavToNextStep = &ContagionPage::SEIARNextStep;
Introduction->Text = L"部分疾病存在具有传染性的无症状感染者,无症状意味着这类人群可能无法察觉自己患病进而无法及时就医,造成更大的人口流动性和更低的康复率。在SEIAR模型中,引入了无症状感染者A,把SEIR模型中的I进一步分为I和A。";
FitInfectiousDisease->Text = L"适用于:2019-nCov 新型冠状病毒肺炎";
RecoveryRate = 0.05;
}
/// <summary>
/// SI下一步
/// </summary>
void AlgorithmVisualization::ContagionPage::SINextStep()
{
for (int i = 0; i < xMax; i++)
{
for (int j = 0; j < yMax; j++)
{
if (GetState(i, j, false) == RectState::Infectious) //如果感染则可以传染给别人
InfectNear(i, j, ContactPeopleCount / 10, InfectiousRate); //传染给周围的人
}
}
}
/// <summary>
/// SIS下一步
/// </summary>
void AlgorithmVisualization::ContagionPage::SISNextStep()
{
for (int i = 0; i < xMax; i++)
{
for (int j = 0; j < yMax; j++)
{
if (GetState(i, j, false) == RectState::Infectious)
{
if (random(e) <= RecoveryRate)
{
SetState(i, j, RectState::Susceptible, true); //在一定概率下转化为易感者
}
else
{
InfectNear(i, j, ContactPeopleCount / 10, InfectiousRate); //如果没有痊愈则继续传染
}
}
}
}
}
/// <summary>
/// SIR下一步
/// </summary>
void AlgorithmVisualization::ContagionPage::SIRNextStep()
{
for (int i = 0; i < xMax; i++)
{
for (int j = 0; j < yMax; j++)
{
if (GetState(i, j, false) == RectState::Infectious)
{
if (random(e) <= RecoveryRate)
{
SetState(i, j, RectState::Recovered, true); //在一定概率下转化为康复者
}
else
{
InfectNear(i, j, ContactPeopleCount / 10, InfectiousRate); //如果没有痊愈则继续传染
}
}
}
}
}
/// <summary>
/// SEIR下一步
/// </summary>
void AlgorithmVisualization::ContagionPage::SEIRNextStep()
{
for (int i = 0; i < xMax; i++)
{
for (int j = 0; j < yMax; j++)
{
if (GetState(i, j, false) == RectState::Infectious)
{
if (random(e) <= RecoveryRate)
{
SetState(i, j, RectState::Recovered, true); //在一定概率下转化为康复者
}
else
{
ChangeToExposed(i, j, ContactPeopleCount / 10, InfectiousRate); //如果没有痊愈则继续传染
}
}
else if (GetState(i, j, false) == RectState::Exposed)
{
if (random(e) <= ExposedToInfectiousRate)
{
SetState(i, j, RectState::Infectious, true); //在一定概率下转化为感染者
}
}
}
}
}
/// <summary>
/// SEIAR下一步
/// </summary>
void AlgorithmVisualization::ContagionPage::SEIARNextStep()
{
for (int i = 0; i < xMax; i++)
{
for (int j = 0; j < yMax; j++)
{
auto rectState = GetState(i, j, false);
if (rectState == RectState::Infectious)
{
if (random(e) <= RecoveryRate)
{
SetState(i, j, RectState::Recovered, true); //在一定概率下转化为康复者
}
else
{
ChangeToExposed(i, j, ContactPeopleCount / 10, InfectiousRate); //如果没有痊愈则继续传染
}
}
else if (rectState == RectState::Asymptomatic)
{
if (random(e) <= AsymptomaticRecoveryRate)
{
SetState(i, j, RectState::Recovered, true); //在一定概率下转化为康复者
}
else
{
ChangeToExposed(i, j, ContactPeopleCount / 10, InfectiousRate); //如果没有痊愈则继续传染
}
}
else if (rectState == RectState::Exposed)
{
if (random(e) <= ExposedToInfectiousRate)
{
SetState(i, j, RectState::Infectious, true); //在一定概率下转化为感染者
}
else if (random(e) <= ExposedToAsymptomaticRate)
{
SetState(i, j, RectState::Asymptomatic, true); //在一定概率下转化为隐性感染者
}
}
}
}
}
/// <summary>
/// 获取状态
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
RectState AlgorithmVisualization::ContagionPage::GetState(int x, int y, bool next)
{
if (next)
return NextStateVector[x][y];
else
return ThisStateVector[x][y];
}
/// <summary>
/// 设置状态
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="newState"></param>
void AlgorithmVisualization::ContagionPage::SetState(int x, int y, RectState newState, bool next)
{
if (next)
NextStateVector[x][y] = newState;
else
ThisStateVector[x][y] = newState;
}
/// <summary>
/// 改变周围的人
/// </summary>
/// <param name="srcX"></param>
/// <param name="srcY"></param>
/// <param name="nearCount"></param>
/// <param name="probability"></param>
void AlgorithmVisualization::ContagionPage::ChangeNear(int srcX, int srcY, int contactCount, double probability, RectState from, RectState to)
{
if (contactCount < 0 || contactCount > 8)
throw ref new InvalidArgumentException(L"临近的人必须是0~8的整数");
//获取邻近的人的状态
auto nearPeople = ref new Vector<Point^>();
for (int i = 0; i < 8; i++)
{
int newX = srcX + DirectionX[i];
int newY = srcY + DirectionY[i];
if (CheckPointValid(newX, newY))
{
nearPeople->Append(ref new Point{ newX, newY });
}
}
while ((int)nearPeople->Size > contactCount) //当目前的人数大于接触到的人数时
{
double rand1 = random(e);
int removeAt = (int)(rand1 * 100000000) % nearPeople->Size;
nearPeople->RemoveAt(removeAt); //随机删除其中一个元素
}
for (unsigned int i = 0; i < nearPeople->Size; ++i)
{
auto people = nearPeople->GetAt(i);
if (GetState(people->x, people->y) == from && random(e) <= probability) //如果满足改变状态的条件
{
SetState(people->x, people->y, to, true); //改变状态
}
}
}
/// <summary>
/// 感染周围人
/// </summary>
/// <param name="srcX"></param>
/// <param name="srcY"></param>
/// <param name="nearCount"></param>
/// <param name="probability"></param>
void AlgorithmVisualization::ContagionPage::InfectNear(int srcX, int srcY, int nearCount, double probability)
{
ChangeNear(srcX, srcY, nearCount, probability, RectState::Susceptible, RectState::Infectious);
}
/// <summary>
/// 使周围人变为潜伏者
/// </summary>
/// <param name="srcX"></param>
/// <param name="srcY"></param>
/// <param name="nearCount"></param>
/// <param name="probability"></param>
void AlgorithmVisualization::ContagionPage::ChangeToExposed(int srcX, int srcY, int nearCount, double probability)
{
ChangeNear(srcX, srcY, nearCount, probability, RectState::Susceptible, RectState::Exposed);
}
/// <summary>
/// 检查点位的合法性
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
bool AlgorithmVisualization::ContagionPage::CheckPointValid(int x, int y)
{
if (x < 0 || y < 0) return false;
if (x >= InfectiousGrid->cols || y >= InfectiousGrid->rows) return false;
return true;
}
/// <summary>
/// 计时器是否在运行
/// </summary>
/// <returns></returns>
bool AlgorithmVisualization::ContagionPage::IsTimerRunning()
{
return ThreadTimer != nullptr;
}
/// <summary>
/// 启动计时器
/// </summary>
void AlgorithmVisualization::ContagionPage::StartTimer()
{
if (!IsTimerRunning())
{
Windows::Foundation::TimeSpan period{};
period.Duration = Speed * 10000; //设置时间间隔
ThreadTimer = ThreadPoolTimer::CreatePeriodicTimer(
ref new TimerElapsedHandler([this](ThreadPoolTimer^ source)
{
GetThisState();
(this->*NavToNextStep)(); //计算出下一步的情况
if (IsTimerRunning() && this != nullptr)
{
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
ref new DispatchedHandler([this]()
{
if (IsTimerRunning() && this != nullptr)
{
LoadNextState(); //将下一步加载到UI上
}
}
));
}
}), period
);
}
}
/// <summary>
/// 结束计时器
/// </summary>
void AlgorithmVisualization::ContagionPage::StopTimer()
{
if (ThreadTimer != nullptr)
{
ThreadTimer->Cancel(); //取消计时器
ThreadTimer = nullptr; //设置计时器为空
}
}
/// <summary>
/// 下一步
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::Next_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
GetThisState();
(this->*NavToNextStep)(); //计算出下一步的情况
LoadNextState(); //将下一步加载到UI上
}
/// <summary>
/// 时间流逝速度改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::TimeElapseSpeedSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
Speed = (int64)(e->NewValue * 1000); //计算出速度
TimeElapseSpeedText->Text = e->NewValue + L"s"; //设置速度的文字
if (IsTimerRunning())
{
//重启计时器
StopTimer();
StartTimer();
}
}
/// <summary>
/// 接触到的人数回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::ContactPeopleCountSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
ContactPeopleCountText->Text = e->NewValue + L"人";
ContactPeopleCount = (int)e->NewValue;
}
/// <summary>
/// 感染率改变时回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::InfectiousRateSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
InfectiousRate = e->NewValue / 100;
}
/// <summary>
/// 开始和暂停按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::StartOrPause_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (IsTimerRunning())
{
StopTimer();
Next->IsEnabled = true;
StartOrPause->Content = L"开始";
}
else
{
StartTimer();
Next->IsEnabled = false;
StartOrPause->Content = L"暂停";
}
}
/// <summary>
/// 恢复率改变时回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::RecoveryRateSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
RecoveryRateText->Text = (int)e->NewValue + L"%";
RecoveryRate = e->NewValue / 100;
}
/// <summary>
/// 重置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::Reset_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
InitAlgorithm(currentType);
}
/// <summary>
/// 潜伏者转正概率改变回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::ExposedToInfectiousSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
ExposedToInfectiousRate = e->NewValue / 100;
if (ExposedToInfectiousRate + ExposedToAsymptomaticRate >= 1.0)
{
ExposedToAsymptomaticRate = 1 - ExposedToInfectiousRate;
ExposedToAsymptomaticSlider->Value = ExposedToAsymptomaticRate * 100;
}
}
/// <summary>
/// 潜伏者转隐性感染者概率改变时回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::ExposedToAsymptomaticSlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
ExposedToAsymptomaticRate = e->NewValue / 100;
if (ExposedToInfectiousRate + ExposedToAsymptomaticRate >= 1.0)
{
ExposedToInfectiousRate = 1 - ExposedToAsymptomaticRate;
ExposedToInfectiousSlider->Value = ExposedToInfectiousRate * 100;
}
}
/// <summary>
/// 隐性感染者康复率改变回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AlgorithmVisualization::ContagionPage::AsymptomaticRecoverySlider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
AsymptomaticRecoveryText->Text = (int)e->NewValue + L"%";
AsymptomaticRecoveryRate = e->NewValue / 100;
}