简易传染病模拟APP的设计与实现(模板模式+MVC模式)

文章脉络

东湖->疫情->众生百态->what can I do for u->微博视频->技术栈->迎接挑战->设计->模型参考SERI->一行行代码->App->发布-SeeCure-App

从东湖说起

在我去过的不多不少的城市里,杭州和武汉是我印象比较深刻的城市。杭州,美。武汉,舒服。杭州有适合雨天去的西湖,武汉有适合雨天去的东湖。

但一场突如其来的疫情,让武汉这座美丽的城市受到了不小的影响。

疫情之下,众生百态,有些超市趁机涨价,有些商人把口罩坐地起价,但正义和法律很快遏止了这一切。而它们的相反面,有些企业捐财捐物资,有些人献温暖献爱心。最令我感动的还是,在危难面前,不顾生死,冲在一线的医生护士们,她们,平凡而伟大,是我眼里最可爱的人。

在感动的同时,我又在想,身为平凡人的我们能做点什么呢?

不出门便是最大的贡献

让我们回顾一下从疫情悄无声息到来,到现在的这段时间,平凡人的那些最可能出现的生活场景。

大年初一前的五天
妈妈不戴口罩的样子像极了你不穿秋裤的样子
大年初一后的五天
好想出去玩
大年初五后的十天
公司怎么还不发通知

而在另外一个地方,一群医生,正昼夜不睡的为拯救病人劳累
身为平凡人的我们,可能不出门便是最大的贡献
当我看到微博上一个计算机仿真程序告诉你为什么还不出门的时候
我不由涌起身为同行的佩服,便也想做一个类似的程序
下文正式讲述我是如何设计这一模型的

基于SARI模型的传染病模拟APP的设计与实现

1.让我们思考如何设计模型

值得一提的是,我在程序写了一半之前是不知道有SERI模型这一说法的,
我想的就是按照我在电视新闻上看到的,以及自己思考的过程来设计的。
我是这样想的:
把人健康状态分为1-100分,选取几个固定的数值模拟几个状态
将一个人按照得病被治愈的时间顺序,分析它可能的健康状态

阶段一:Health (健康状态)
阶段二:Infect (感染但没有发病)
阶段三:Disease (发病状态)
阶段四:DiseaseInCare (进入病房救治ing)
阶段五:DiseaseRecure (被治愈,产生抗体)or Death (死亡)

public class HealthState {
    public static int Health = 100;
    public static int DiseaseRecure = 80;
    public static int DiseaseInCare = 60;
    public static int Infect = 40;
    public static int Disease = 20;
    public static int Death = 0;

    public static int getColor(int healthState) {
        if(healthState == Health) {
            return R.color.healthstate100;
        }else if(healthState == DiseaseInCare) {
            return R.color.healthstate60;
        }else if(healthState == Infect) {
            return R.color.healthstate40;
        }else if(healthState == Disease) {
            return R.color.healthstate20;
        }else {
            return R.color.healthstate0;
        }
    }
}

写到一半我想查查资料,结果发现有SERI模型这么一说,好,让我们的模型更符合真实的数学模型,学习一波。

2.SERI模型是什么

SERI模型是传染病的基本数学模型
S: 潜在的可能被感染的人
E: 代表已经被感染但没发病的人
I: 代表发病的人
R: 代表有抗体的人

扫描二维码关注公众号,回复: 11130862 查看本文章

针对不同特征的的传染病又分为SIS,SIR,SERI模型,
带有潜伏期的适合用SERI模型,即S->E->R->I的过程
你看,正和我们当初思考的一样。

3.让我们继续思考模型

首先我们先假设在某个平行世界里有一座虚拟的城市。我们需要选择一些参数模拟这座城市的初始情况,选取参数的原则是参数间原则上彼此独立且对传染病的传播和抑制有重要影响,所以最好可以听这方面的专家的建议(专家经验),我综合参考了一些信息,选取了以下的参数:
城市初始人数,初始感染人数(初始情况)
传染病潜伏期(决定传染但不发病到发病的时间)
传染病传染率,人群的流动率(决定传染的速度)
医院的病床数,平均收治时间,药物的治愈率(决定治疗效果)

由于我们使用面向对象的语言Java,那我们这次最主要的对象就是人People对象
一群人我们可以用peoples(其类型是List<People>)表示,此刻我们惊奇的发现,这个List包含了我们用到的一切。模拟城市的所有人,还有他们的健康状态。好,让我们来定义一个People对象

public class People {

    public int serialNumber;//身份证ID
    public int healthState;//人健康状态,对应上边的HealthState类
    public int incubationDays;//病毒在这个人身上的潜伏期
    public int sickenDay;//感染上病的天数,没感染则为0
    public int beInHospitalDays;//感染上病到可以住上院的间隔天数
    public int goOutToday;//今天是否外出
    public int antiBody;//是否产生抗体

    public People() {}

    public People(int number, int healthState, int incubationDays, int sickenday, int beInHospitalDays, int goOutToday, int antiBody) {
        this.serialNumber = number;
        this.healthState = healthState;
        this.incubationDays = incubationDays;
        if(this.healthState == HealthState.Health) {
            this.sickenDay = 0;
        }else {
            this.sickenDay = sickenday;
        }
        this.beInHospitalDays = beInHospitalDays;
        this.goOutToday = goOutToday;
        this.antiBody = antiBody;
    }

    public int getSerialNumber() {
        return serialNumber;
    }

    public void setSerialNumber(int serialNumber) {
        this.serialNumber = serialNumber;
    }

    public int getHealthState() {
        return healthState;
    }

    public void setHealthState(int healthState) {
        this.healthState = healthState;
    }

    public int getIncubationDays() {
        return incubationDays;
    }

    public void setIncubationDays(int incubationDays) {
        this.incubationDays = incubationDays;
    }

    public int getSickenDay() {
        return sickenDay;
    }

    public void setSickenDay(int sickenDay) {
        this.sickenDay = sickenDay;
    }

    public int getBeInHospitalDays() {
        return beInHospitalDays;
    }

    public void setBeInHospitalDays(int beInHospitalDays) {
        this.beInHospitalDays = beInHospitalDays;
    }

    public int getGoOutToday() {
        return goOutToday;
    }

    public void setGoOutToday(int goOutToday) {
        this.goOutToday = goOutToday;
    }

    public int getAntiBody() {
        return antiBody;
    }

    public void setAntiBody(int antiBody) {
        this.antiBody = antiBody;
    }
}

4.开始模拟传染过程

仔细分析我们要实现的传染病模型,每一个人(People)所处的健康状态,其实就是一个有限状态机(是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型)。不生病 <- 健康 -> 被传染但未发病 -> 生病 -> 住院 -> 健康。

那么模拟整座虚拟城市,其实就是一个List<People>中People的健康状态不断变化的过程。所以我们通过初始化的一些参数,每次更新List<People>里的People的健康状态,并实时显示出来它们的状态,便可以模拟传染病的传染过程。

那么我是如何写代码来模拟这一复杂过程的呢,首先来介绍一个这个很常用的设计模式:
Template Method(可叫做模板方法,或者模板模式):
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

我的方法便是使用流水线方法,这个思想借鉴了这个设计模式,只是不是在抽象类中公开定义了执行它的方法的方式/模板,而是在方法中用函数模拟流行病传染的过程:

peoples = initPeopleHealthState();//初始化人群S,E的分布状态

peoples = SickenToDisease(peoples);//SERI模型E->R
peoples = DiseaseToCureOrDeath(peoples);
peoples = AntinodeToPeople(peoples);//SERI模型R->I
peoples = SpreadToEachOther(peoples);//SERI模型S->E

这里的peoples是静态变量。

initPeopleHealthState(),这一函数初始化人群模拟的是SERI模型的S,E的分布状态,这一阶段关键指标是:城市初始人数和初始感染人数。

后面的这四行代码放在线程里,按照1s更新一次,模拟现实世界里的一天。这四行代码分别用到了四个函数。

SickenToDisease(peoples),这一函数模拟人群中感染但未发病的人,模拟的是SERI模型从E->R的这一阶段,这一阶段关键指标是:传染病潜伏期

DiseaseToCureOrDeath(peoples),这一函数模拟人群中发病到治疗的过程,SERI模型R->I的这一阶段,这一阶段关键指标是:医院病床数和收治时间

AntinodeToPeople(peoples),这一函数模拟人群中接受治疗到健康的过程,SERI模型I->S的这一阶段,这一阶段关键指标是:药物的治愈率

SpreadToEachOther(peoples),这一函数模拟人群中健康的人被感染的过程,模拟的是SERI模型从S->E模型,这一阶段关键指标是:传染病传染率,人群的流动率

5.将List<People>可视化

现在我们只需要把我们前面定义的函数放在适合的前端展示即可,将不同类型的人用不同的颜色区分即可模拟传染病传播的过程。
值得一提的是,我们的整个模型也用到了MVC(模型-视图-控制器)这一经典模式,M是我们的List<People>(数据),V是指适合的前端(视图),C是指我们的流水线方法(控制)
初始化在这里插入图片描述
在这里插入图片描述

6.下载体验地址

SeeCure APP — Design By Wang Yu Zhou

发布了7 篇原创文章 · 获赞 4 · 访问量 2259

猜你喜欢

转载自blog.csdn.net/qq_32648593/article/details/104247082