Skip to content

Commit

Permalink
- 添加按钮来观看不同状态下的感染情况
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Feb 16, 2020
1 parent 427e233 commit e37164e
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 33 deletions.
50 changes: 29 additions & 21 deletions src/Constants.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.util.Timer;

/**
* 模拟参数
*
Expand All @@ -8,26 +10,32 @@
*/
public class Constants {

public static int ORIGINAL_COUNT = 50;//初始感染数量
public static float BROAD_RATE = 0.8f;//传播率
public static float SHADOW_TIME = 140;//潜伏时间,14天为140
public static int HOSPITAL_RECEIVE_TIME = 10;//医院收治响应时间,1天
public static int BED_COUNT = 1000;//医院床位
/**
* 流动意向平均值,建议调整范围:[-0.99,0.99]
* <p>
* -0.99 人群流动最慢速率,甚至完全控制疫情传播
* 0.99为人群流动最快速率, 可导致全城感染
*/
public static float u = 0.99f;
public static int CITY_PERSON_SIZE = 5000;//城市总人口数量
public static float FATALITY_RATE = 0.50f;//fatality_rate病死率,根据2月6日数据估算(病死数/确诊数)为0.02
public static int DIE_TIME = 100;//死亡时间均值,10天,从发病(确诊)时开始计时
public static double DIE_VARIANCE = 1;//死亡时间方差
/**
* 城市大小即窗口边界,限制不允许出城
*/
public static final int CITY_WIDTH = 700;
public static final int CITY_HEIGHT = 800;
public static int ORIGINAL_COUNT = 50;// 初始感染数量
public static float BROAD_RATE = 0.8f;// 传播率
public static float SHADOW_TIME = 140;// 潜伏时间,14天为140
public static int HOSPITAL_RECEIVE_TIME = 10;// 医院收治响应时间,1天
public static int BED_COUNT = 1000;// 医院床位

// public static int NEED_BED_COUNT = 0;// 急需医院床位
/**
* 流动意向平均值,建议调整范围:[-0.99,0.99]
* <p>
* -0.99 人群流动最慢速率,甚至完全控制疫情传播 0.99为人群流动最快速率, 可导致全城感染
*/
public static float u = -0.99f;
public static int CITY_PERSON_SIZE = 5000;// 城市总人口数量
public static float FATALITY_RATE = 0.50f;// fatality_rate病死率,根据2月6日数据估算(病死数/确诊数)为0.02
public static int DIE_TIME = 100;// 死亡时间均值,10天,从发病(确诊)时开始计时
public static double DIE_VARIANCE = 1;// 死亡时间方差
/**
* 城市大小即窗口边界,限制不允许出城
*
*
*/
public static final int CITY_WIDTH = 700;
public static final int CITY_HEIGHT = 800;//整个窗体的高度


public static Timer timer = new Timer();

}
99 changes: 97 additions & 2 deletions src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

import java.util.List;
import java.util.Random;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.event.MenuListener;

import javax.swing.event.MenuEvent;

/**
* 模拟程序主入口
Expand All @@ -24,13 +33,80 @@ private static void initPanel() {
MyPanel p = new MyPanel();
Thread panelThread = new Thread(p);
JFrame frame = new JFrame();
frame.add(p);
frame.getContentPane().add(p);
frame.setSize(Constants.CITY_WIDTH + hospitalWidth + 300, Constants.CITY_HEIGHT);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setTitle("瘟疫传播模拟——————新冠状病毒");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panelThread.start();// 开启画布线程,即世界线程,接着看代码的下一站可以转MyPanel.java

JPopupMenu popupMenu = new JPopupMenu();
addPopup(frame, popupMenu);

JMenuItem menuItem = new JMenuItem("关于");
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

JOptionPane.showMessageDialog(null, "武汉加油!湖北加油!中国加油!");
}
});
popupMenu.add(menuItem);

JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);

JMenu menu = new JMenu("控制人口流动");
menu.addMenuListener(new MenuListener() {
public void menuCanceled(MenuEvent e) {
}

public void menuDeselected(MenuEvent e) {
}

public void menuSelected(MenuEvent e) {

Constants.u = -0.99f;
resetWorld();

}
});

menuBar.add(menu);

JMenu menu_1 = new JMenu("不控制人口流动");
menu_1.addMenuListener(new MenuListener() {

public void menuCanceled(MenuEvent e) {
}

public void menuDeselected(MenuEvent e) {
}

public void menuSelected(MenuEvent e) {
Constants.u = 0.99f;
resetWorld();
}
});
menuBar.add(menu_1);

frame.setVisible(true);
}

/**
* 重新开始
*/
static void resetWorld() {
List<Person> people = PersonPool.getInstance().getPersonList();
for (Person person : people) {
person.setState(Person.State.NORMAL);
}

List<Bed> beds = Hospital.getInstance().getBeds();
for (Bed bed : beds) {
bed.setEmpty(true);
}

initInfected();
}

/**
Expand Down Expand Up @@ -64,4 +140,23 @@ private static void initInfected() {
}
}

private static void addPopup(Component component, final JPopupMenu popup) {
component.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showMenu(e);
}
}

public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showMenu(e);
}
}

private void showMenu(MouseEvent e) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
}
}
55 changes: 45 additions & 10 deletions src/MyPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,26 @@ public MyPanel() {
public void paint(Graphics g) {
// 保留每次绘制的图像
super.paint(g);
g.setColor(new Color(0x00ff00));// 设置医院边界颜色
// 绘制医院边界
g.drawRect(Hospital.getInstance().getX(), Hospital.getInstance().getY(), Hospital.getInstance().getWidth(),
Hospital.getInstance().getHeight());
// 写标题
g.setFont(new Font("微软雅黑", Font.BOLD, 16));
g.setColor(new Color(0x00ff00));
g.setColor(new Color(0xffffff));
g.drawString("医院", Hospital.getInstance().getX() + Hospital.getInstance().getWidth() / 4,
Hospital.getInstance().getY() - 16);

g.setColor(new Color(0xffffff));// 设置医院边界颜色,白色
// 绘制医院边界
g.drawRect(Hospital.getInstance().getX(), Hospital.getInstance().getY(), Hospital.getInstance().getWidth(),
Hospital.getInstance().getHeight());

g.setColor(new Color(0xffffff));
int ref = 15;
g.drawLine(Hospital.getInstance().getX() + Hospital.getInstance().getWidth() + ref, 0,
Hospital.getInstance().getX() + Hospital.getInstance().getWidth() + ref, Constants.CITY_HEIGHT);

// 绘制代表人类的圆点
// 以单个人为单位的数组,即人群
List<Person> people = PersonPool.getInstance().getPersonList();
// 人群数为0不继续执行
// 总人数为0不继续执行
if (people == null) {
return;
}
Expand Down Expand Up @@ -119,23 +126,51 @@ public void paint(Graphics g) {
* 医院床位满了之后,新确诊的都没有床位可用,都属于急需病床
*
* 急需病床数=确诊人数-空余床位
*/ int needBeds = PersonPool.getInstance().getPeopleSize(Person.State.CONFIRMED)
*/
int needBeds = PersonPool.getInstance().getPeopleSize(Person.State.CONFIRMED)
- Math.max(Constants.BED_COUNT - PersonPool.getInstance().getPeopleSize(Person.State.FREEZE), 0);
g.drawString("急需病床:" + (needBeds > 0 ? needBeds : 0), captionStartOffsetX,
captionStartOffsetY + 7 * captionSize);

g.setColor(new Color(0xccbbcc));
g.drawString("病死人数:" + PersonPool.getInstance().getPeopleSize(Person.State.DEATH), captionStartOffsetX,
captionStartOffsetY + 8 * captionSize);
g.setColor(new Color(0xffffff));
// 每秒增加一天
g.drawString("世界时间(天):" + (int) (worldTime / 10.0), captionStartOffsetX, captionStartOffsetY + 9 * captionSize);

g.setColor(new Color(0xffffff));
g.drawLine(captionStartOffsetX, captionStartOffsetY + 9 * captionSize + 5, captionStartOffsetX + 300,
captionStartOffsetY + 9 * captionSize + 5);

g.drawString("人群移动意向:" +new Person(null,0,0).wantMoveSubs(Constants.u), captionStartOffsetX, captionStartOffsetY + 10 * captionSize);



//失控
if(PersonPool.getInstance().getPeopleSize(Person.State.NORMAL)<=3) {


g.setFont(new Font("微软雅黑", Font.BOLD, 50));
g.setColor(new Color(0xffffff));
g.drawString("不抛弃!不放弃!", getWidth()/100,
getHeight()/2);

}
//控制住了
if(PersonPool.getInstance().getPeopleSize(Person.State.SHADOW)==0&&PersonPool.getInstance().getPeopleSize(Person.State.CONFIRMED)==0) {

g.setFont(new Font("微软雅黑", Font.BOLD, 50));
g.setColor(new Color(0xffffff));
g.drawString("防疫阻击战获得了胜利!!!", getWidth()/100,
getHeight()/2);
}


}

public static int worldTime = 0;// 世界时间

public Timer timer = new Timer();

/*
*
* 不断调用paint方法,刷新图形
Expand All @@ -161,7 +196,7 @@ public void run() {
*/
@Override
public void run() {
timer.schedule(new MyTimerTask(), 0, 100);// 启动世界计时器,时间开始流动(突然脑补DIO台词:時は停た)
Constants.timer.schedule(new MyTimerTask(), 0, 100);// 启动世界计时器,时间开始流动(突然脑补DIO台词:時は停た)
}

}
6 changes: 6 additions & 0 deletions src/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public boolean wantMove() {
return MathUtil.stdGaussian(sig, Constants.u) > 0;
}

String wantMoveSubs(float x) {
return x > 0.5 ? "人们随意走动" : "人们限制出行";
}

private int state = State.NORMAL;

public int getState() {
Expand Down Expand Up @@ -252,9 +256,11 @@ public void update() {
if (bed == null) {

// 没有床位了,报告需求床位数
// Constants.NEED_BED_COUNT++;

} else {
// 安置病人
// 移到医院区域,这个时候小点依然是红色。会出现这种情况:一轮循环在下一轮开始前移动很多红点到医院区域,下一轮开始之后才变为蓝色
useBed = bed;
state = State.FREEZE;
setX(bed.getX());
Expand Down

0 comments on commit e37164e

Please sign in to comment.