stuck, need improve speed

This commit is contained in:
Yong Zhu 2019-03-08 01:24:16 -07:00
parent 4a1c0fd630
commit 0efc6b9021
22 changed files with 755 additions and 191 deletions

29
.gitignore vendored
View File

@ -1,19 +1,20 @@
# Bat files
*.bat
/build/
target/
bin/
.project
.classpath
.settings/
*~
*.orig
*.new
.idea/
*.iml
*.ipr
test/**/build/
examples/**/build/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
@ -21,5 +22,5 @@
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
# virtual machine crash logs
hs_err_pid*

1
command.bat Normal file
View File

@ -0,0 +1 @@
cmd

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

View File

@ -57,6 +57,14 @@
<dependencies>
<!-- For JSON translate -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

3
core/run.bat Normal file
View File

@ -0,0 +1,3 @@
cd target\classes
java -classpath ".;*" com.github.drinkjava2.frog.env.Application
@pause

View File

@ -1,23 +0,0 @@
package com.github.drinkjava2.env;
import javax.swing.JFrame;
/**
* Application will build env, frogs and let them run
*/
public class Application {
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame();
frame.setLayout(null);
frame.setSize(Env.XSIZE + 220, Env.YSIZE + 250); // 窗口大小
frame.setTitle("Stage#1: First Artifical Life"); // 标题
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
Env env = new Env();
frame.add(env);
frame.setVisible(true);
env.run();
}
}

View File

@ -1,80 +0,0 @@
package com.github.drinkjava2.env;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import com.github.drinkjava2.frog.Frog;
/**
* Env is the living space of frog. Use Java Swing to drawing the environment.
*/
@SuppressWarnings("serial")
public class Env extends JButton {
/** Metric width is 500 pixels */
public static final int XSIZE = 300;
/** Metric height is 500 pixels */
public static final int YSIZE = 300;
public int frogAmount = 10;
public int foodAmount = 500;
public List<Frog> frogs = new ArrayList<Frog>();
public List<Food> foods = new ArrayList<Food>();
public Env() {
super();
this.setLayout(null);// 空布局
this.setBounds(100, 100, XSIZE, YSIZE);
Random rand = new Random();
for (int i = 0; i < frogAmount; i++)
frogs.add(new Frog(rand.nextInt(Env.XSIZE - 3), rand.nextInt(Env.YSIZE - 3)));
for (int i = 0; i < foodAmount; i++)
foods.add(new Food(rand.nextInt(Env.XSIZE - 3), rand.nextInt(Env.YSIZE - 3)));
}
public void eatFoods() {
eating = true;
for (Frog frog : frogs) {
int j = foods.size() - 1;
for (int i = j; i >= 0; i--) {
Food food = foods.get(i);
if (frog.x == food.x && frog.y == food.y)
foods.remove(i);
}
}
eating = false;
}
static boolean eating = true;
public void run() throws InterruptedException {
Random r = new Random();
int count = 0;
do {
count++;
for (Frog frog : frogs) {
frog.x += r.nextInt(3) - 1;
frog.y += r.nextInt(3) - 1;
}
eatFoods();
if (count % 50 != 0)
continue;
Image buffImg = createImage(this.getWidth(), this.getHeight());
Graphics g = buffImg.getGraphics();
for (Frog frog : frogs)
frog.show(g);
for (Food food : foods)
food.show(g);
Graphics g2 = this.getGraphics();
g2.drawImage(buffImg, 0, 0, this);
Thread.sleep(10);
} while (true);
}
}

View File

@ -1,21 +0,0 @@
package com.github.drinkjava2.env;
import java.awt.Graphics;
/**
* Food is food for frogs, one food = 100 unit energy
*/
public class Food {
int x;
int y;
public Food(int x, int y) {
this.x = x;
this.y = y;
}
public void show(Graphics g) {
g.fillOval(x, y, 4, 4);
}
}

View File

@ -12,46 +12,202 @@ package com.github.drinkjava2.frog;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import com.github.drinkjava2.frog.brain.Brain;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Output;
import com.github.drinkjava2.frog.egg.CellGroup;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.egg.Zone;
import com.github.drinkjava2.frog.env.Application;
import com.github.drinkjava2.frog.env.Env;
/**
* Frog = brain + body(mouth, eye, leg)
* Frog = brain + body(mouth, eye, leg), but now let's focus on brain, ignore
* body
*
* 为了简化模型这个类里出现多个固定数值的编码以后要改进成可以可以放在蛋里遗传进化的动态数值先让生命延生是第一步优化是以后的事
*
* @author Yong Zhu
* @since 1.0.0
*/
public class Frog {
/** brain radius virtual unit */
public float brainRadius;
/** brain cells */
List<Cell> cells = new ArrayList<Cell>();
/** 视觉细胞的输入区在脑中的坐标,先随便取 在原点附件就可以了分瓣率为60x60, 以后再考虑放到蛋里去进化 */
public static int eyeRadius = Math.round(30);
/** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
public static Zone moveUp = new Zone(500, 100, 10);
public static Zone moveDown = new Zone(500, 200, 10);
public static Zone moveLeft = new Zone(500, 300, 10);
public static Zone moveRight = new Zone(500, 400, 10);
public int x;
public int y;
public int face = 1 + new Random().nextInt(4); // 0:sleep 1:up 2:right 3:down 4:left 5:right
public int move = 0; // 0: stop 1:up 2:right 3:down 4:left 5:right turn 6 left turn
public long energy = 10000;
public long energy = Env.STEPS_PER_ROUND;
public Egg egg;
static final Random r = new Random();
static Image frogImg;
static {
try {
frogImg = ImageIO.read(new FileInputStream(new File("").getAbsolutePath() + "/frog.png"));
frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
Brain brain;
public Frog(int x, int y) {
public Frog(int x, int y, Egg egg) {
this.x = x;
this.y = y;
if (egg.cellgroups == null)
throw new IllegalArgumentException("Illegal egg cellgroups argument:" + egg.cellgroups);
this.brainRadius = egg.brainRadius;
for (int k = 0; k < egg.cellgroups.length; k++) {
CellGroup g = egg.cellgroups[k];
for (int i = 0; i < g.cellQty; i++) {// 开始根据蛋来创建脑细胞
Cell c = new Cell();
c.inputs = new Input[g.inputQtyPerCell];
for (int j = 0; j < g.inputQtyPerCell; j++) {
c.inputs[j] = new Input();
c.inputs[j].cell = c;
Zone.copyXY(randomPosInZone(g.groupInputZone), c.inputs[j]);
c.inputs[j].radius = g.cellInputRadius;
}
c.outputs = new Output[g.outputQtyPerCell];
for (int j = 0; j < g.outputQtyPerCell; j++) {
c.outputs[j] = new Output();
c.outputs[j].cell = c;
Zone.copyXY(randomPosInZone(g.groupInputZone), c.outputs[j]);
c.outputs[j].radius = g.cellOutputRadius;
}
cells.add(c);
}
}
this.egg = egg;// 保留一份蛋如果没被淘汰掉将来下蛋时要用这个蛋来下新蛋
}
public void show(Graphics g) {
g.drawLine(x, y-2, x, y+2);
g.drawImage(frogImg, x - 16, y - 16, 32, 32, null);
public void active(Env env) {
// 每个step即使啥都不干也要消耗能量
energy--;
// 如果青蛙位置与food重合吃掉它
boolean eatedFood = false;
if (x >= 0 && x < env.ENV_XSIZE && y > 0 && y < env.ENV_YSIZE)
if (env.foods[x][y] > 0) {
env.foods[x][y] = 0;
energy = energy + 1000;// 吃掉food能量境加
eatedFood = true;
}
// 吃掉food有奖励
if (eatedFood) {
}
for (Cell cell : cells) {
// 输入部分
for (Input input : cell.inputs) {
// 如果食物出现在视觉区激活对应frog视觉区的输入触突
if (input.x > (-eyeRadius) && input.y > (-eyeRadius) && input.x < eyeRadius && input.y < eyeRadius) {
int xx = x + input.roundX();
int yy = y + input.roundY();
if (xx > 0 && xx < env.ENV_XSIZE && yy > 0 && yy < env.ENV_YSIZE && env.foods[xx][yy] > 0)
input.energy += 500;
}
// 如果任意输入触突激活增加对应细胞的输出区激活
if (input.energy > 50)
cell.activateOutputs();
// 即使什么也不干input的能量总在以95%的速度下降
input.energy *= .95;
}
// 如果输出触突位于运动区且兴奋则frog移动一个单位
for (Output output : cell.outputs) {
// if (output.energy < 30)
// continue;
if (moveUp.nearby(output)) {
y += 1;
}
if (moveDown.nearby(output)) {
y -= 1;
}
if (moveLeft.nearby(output)) {
x -= 1;
}
if (moveRight.nearby(output)) {
x += 1;
}
// 即使什么也不干output的能量总在以95%的速度下降
output.energy *= 0.95;
}
}
}
private boolean allowVariation = false;
private float percet1(float f) {
if (!allowVariation)
return f;
return (float) (f * (0.99f + r.nextFloat() * 0.02));
}
private float percet5(float f) {
if (!allowVariation)
return f;
return (float) (f * (0.95f + r.nextFloat() * 0.10));
}
private static Zone randomPosInZone(Zone z) {
return new Zone(z.x - z.radius + z.radius * 2 * r.nextFloat(), z.y - z.radius + z.radius * 2 * r.nextFloat(),
0);
}
public Egg layEgg() {
if (r.nextInt(100) > 75) // 变异率先固定在75%
allowVariation = false;// 如果不允许变异下的蛋就相当于克隆原来的蛋
else
allowVariation = true;
Egg newEgg = new Egg();
newEgg.brainRadius = percet5(egg.brainRadius);
CellGroup[] cellgroups = new CellGroup[egg.cellgroups.length];
newEgg.cellgroups = cellgroups;
for (int i = 0; i < cellgroups.length; i++) {
CellGroup cellGroup = new CellGroup();
cellgroups[i] = cellGroup;
CellGroup oldGp = egg.cellgroups[i];
cellGroup.groupInputZone = new Zone(percet5(oldGp.groupInputZone.x), percet5(oldGp.groupInputZone.y),
percet5(oldGp.groupInputZone.radius));
cellGroup.groupOutputZone = new Zone(percet5(oldGp.groupOutputZone.x), percet5(oldGp.groupOutputZone.y),
percet5(oldGp.groupOutputZone.radius));
cellGroup.cellQty = Math.round(percet5(oldGp.cellQty));
cellGroup.cellInputRadius = percet1(oldGp.cellInputRadius);
cellGroup.cellOutputRadius = percet1(oldGp.cellOutputRadius);
cellGroup.inputQtyPerCell = Math.round(percet5(oldGp.inputQtyPerCell));
cellGroup.outputQtyPerCell = Math.round(percet5(oldGp.outputQtyPerCell));
}
return newEgg;
}
public void show(Graphics g) {
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
}
}

View File

@ -11,21 +11,20 @@
package com.github.drinkjava2.frog.brain;
/**
* Cell represents a brain nerve cell, this is the basic unit of brain
* Cell is a brain nerve cell, this is the basic unit of frog's brain
*
* @author Yong Zhu
* @since 1.0.0
*/
public class Cell {
public int x;
public int y;
public int active;
public int drop;
public int inX;
public int inY;
public int inSize;
public int outX;
public int outY;
public int outSize;
public int fat;
public int group; // this cell belong to which group?
public Input[] inputs; // inputs of cell
public Output[] outputs; // outputs of cell
public boolean used = false;
public void activateOutputs() {
for (Output output : outputs)
output.energy += 55;
}
}

View File

@ -8,11 +8,17 @@
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog;
package com.github.drinkjava2.frog.brain;
import com.github.drinkjava2.frog.egg.Zone;
/**
* Egg is the static description of frog, can save as text file
* Input is the sensor of nerve cell
*
* @author Yong Zhu
* @since 1.0.0
*/
public class Egg {
public class Input extends Zone{
public float energy;
public Cell cell;
}

View File

@ -10,33 +10,15 @@
*/
package com.github.drinkjava2.frog.brain;
import com.github.drinkjava2.frog.egg.Zone;
/**
* Brain is consisted by lots of cells
* Output can active other nerve cell's input
*
* @author Yong Zhu
* @since 1.0.0
*/
public class Brain {
/** Brain dimension X is 10000 cells */
private int xSize = 10000;
/** Brain dimension Y is 100 cells */
private int ySize = 1000;
/** Brain dimension Z is 10 cells */
private int zSize = 10;
/** cells in brain */
public Cell[][][] cells;
public Brain() {
cells = new Cell[xSize][ySize][zSize];
}
public Brain(int xSize, int ySize, int zSize) {
this.xSize = xSize;
this.ySize = ySize;
this.zSize = zSize;
cells = new Cell[xSize][ySize][zSize];
}
public class Output extends Zone {
public float energy;
public Cell cell;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.egg;
import java.io.Serializable;
/**
* CellGroup represents a bunch of similar nerve cells <br/>
*
* CellGroup代表了一束相同功能和结构分布位置相近的脑神经元目的是为了下蛋时简化串行化海量的神经元,
* 只需要在egg里定义一组cellGroup就行了不需要将海量的一个个的神经元串行化存放到egg里这样一来Frog就不能"永生"因为每一个egg都不等同于
* 它的母体 而且每一次测试一些复杂的条件反射的建立都必须从头开始训练在项目后期有可能每个frog生命的一半时间都花在重新建立条件反射的学习过程中
*
* 模拟一公一母两个蛋受精CellGroup叠加也许很fun,这样可以将不同环境训练出的蛋叠加成一个但现在暂时不考虑
*
* @author Yong Zhu
* @since 1.0.0
*/
public class CellGroup implements Serializable {
private static final long serialVersionUID = 1L;
public Zone groupInputZone; // input distribute zone
public Zone groupOutputZone; // output distribute zone
public float cellInputRadius; // input radius of each cell
public float cellOutputRadius; // output radius of each cell
public int cellQty; // how many nerve cells in this CellGroup
public int inputQtyPerCell; // input qty per cell
public int outputQtyPerCell; // output qty per cell
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.egg;
import java.io.Serializable;
import java.util.Random;
/**
* Egg is the static structure description of frog, can save as text file, to
* build a frog, first need build a egg.<br/>
*
* 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述而不是Frog本身这样一来Frog就不能"永生"因为每一个egg都不等同于
* 它的母体 而且每一次测试大部分条件反射的建立都必须从头开始训练类似于人类无论人类社会有多聪明 婴儿始终是一张白纸需要花大量的时间从头学习
*
*/
public class Egg implements Serializable {
private static final long serialVersionUID = 2L;
public static final int CELL_GROUP_QTY = 30;
public float brainRadius = 100;
public CellGroup[] cellgroups;
public static Egg createBrandNewEgg() {
Egg egg = new Egg();
Random r = new Random();
egg.cellgroups = new CellGroup[CELL_GROUP_QTY];
for (int i = 0; i < CELL_GROUP_QTY; i++) {
CellGroup cellGroup = new CellGroup();
egg.cellgroups[i] = cellGroup;
cellGroup.groupInputZone = new Zone(r.nextFloat() * egg.brainRadius, r.nextFloat() * egg.brainRadius,
(float) (r.nextFloat() * egg.brainRadius * .01));
cellGroup.groupOutputZone = new Zone(r.nextFloat() * egg.brainRadius, r.nextFloat() * egg.brainRadius,
(float) (r.nextFloat() * egg.brainRadius * .01));
cellGroup.cellQty = r.nextInt(30);
cellGroup.cellInputRadius = (float) (r.nextFloat());
cellGroup.cellOutputRadius = (float) (r.nextFloat() );
cellGroup.inputQtyPerCell = r.nextInt(10);
cellGroup.outputQtyPerCell = r.nextInt(5);
}
return egg;
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.egg;
import java.io.Serializable;
/**
* Zone represents a position in brain
*
* @author Yong Zhu
* @since 1.0.0
*/
public class Zone implements Serializable {
private static final long serialVersionUID = 3L;
public float x;
public float y;
public float radius;
public Zone() {
// 空构造器不能省FastJSON实例化时要用到
}
public Zone(float x, float y, float radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public boolean nearby(Zone z) {
float dist = radius + z.radius;
if (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist)
return true;
return false;
}
public int roundX() {
return Math.round(x);
}
public int roundY() {
return Math.round(y);
}
public static void copyXY(Zone from, Zone to) {
to.x = from.x;
to.y = from.y;
}
}

View File

@ -0,0 +1,30 @@
package com.github.drinkjava2.frog.env;
import java.io.File;
import javax.swing.JFrame;
/**
* Application will build env, frogs and let them run
*/
public class Application {
public static final String CLASSPATH;
static {
String classpath = new File("").getAbsolutePath();
int core = classpath.indexOf("core");
CLASSPATH = classpath.substring(0, core);
}
public static JFrame mainFrame = new JFrame();
public static void main(String[] args) throws InterruptedException {
mainFrame.setLayout(null);
mainFrame.setSize(520, 550); // 窗口大小
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
Env env = new Env();
mainFrame.add(env);
mainFrame.setVisible(true);
env.run();
}
}

View File

@ -0,0 +1,96 @@
package com.github.drinkjava2.frog.env;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JPanel;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.util.EggTool;
/**
* Env is the living space of frog. draw it on JPanel
*/
@SuppressWarnings("serial")
public class Env extends JPanel {
/** Speed of test */
public static int SHOW_SPEED = 100;
/** Steps of one test round */
public static int STEPS_PER_ROUND = 1000;
/** Virtual environment x size is 500 pixels */
public int ENV_XSIZE = 300;
/** Virtual environment y size is 500 pixels */
public int ENV_YSIZE = 300;
public byte[][] foods = new byte[ENV_XSIZE][ENV_YSIZE];
public int FOOD_QTY =6000; // as name
public int EGG_QTY = 2; // as name
public List<Frog> frogs = new ArrayList<Frog>();
public List<Egg> eggs;
public Env() {
super();
this.setLayout(null);// 空布局
this.setBounds(100, 100, ENV_XSIZE, ENV_YSIZE);
}
private void rebuildFrogAndFood() {
frogs.clear();
for (int i = 0; i < ENV_XSIZE; i++) {
for (int j = 0; j < ENV_YSIZE; j++) {
foods[i][j] = 0;
}
}
Random rand = new Random();
for (int i = 0; i < eggs.size(); i++) { // 1个Egg生出10个Frog
for (int j = 0; j < 10; j++) {
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
}
}
for (int i = 0; i < FOOD_QTY; i++)
foods[rand.nextInt(ENV_XSIZE - 3)][rand.nextInt(ENV_YSIZE - 3)] = 1;
}
private void drawFood(Graphics g) {
for (int x = 0; x < ENV_XSIZE; x++)
for (int y = 0; y < ENV_YSIZE; y++)
if (foods[x][y] > 0) {
g.fillOval(x, y, 4, 4);
}
}
public void run() throws InterruptedException {
EggTool.loadEggs(this); // 从磁盘加载egg或新建一批egg
int round = 1;
do {
Application.mainFrame.setTitle("Frog test round: " + round++);
rebuildFrogAndFood();
for (int i = 0; i < STEPS_PER_ROUND; i++) {
for (Frog frog : frogs)
frog.active(this);
if (i % SHOW_SPEED != 0) // 显示会拖慢速度
continue;
Image buffImg = createImage(this.getWidth(), this.getHeight());
Graphics g = buffImg.getGraphics();
for (Frog frog : frogs)
frog.show(g);
drawFood(g);
Graphics g2 = this.getGraphics();
g2.drawImage(buffImg, 0, 0, this);
Thread.sleep(10);
}
EggTool.layEggs(this);
} while (true);
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.util;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.env.Application;
import com.github.drinkjava2.frog.env.Env;
/**
* Egg is the static structure description of frog, can save as text file, to
* build a frog, first need build a egg.
*/
public class EggTool {
public static final boolean JSON_FILE_FORMAT = false; // JSON is slow but easier to debug
/**
* 利用Java串行机制存盘 能量多(也就是吃的更多更fat)的Frog下蛋并存盘, 以进行下一伦测试能量少的Frog被淘汰没有下蛋的资格
*/
public static void layEggs(Env env) {
sortFrogsOrderByEnergyDesc(env);
System.out.print("First frog energy=" + env.frogs.get(0).energy);
System.out.print(", Last frog energy=" + env.frogs.get(env.frogs.size() - 1).energy + ", ");
for (Frog frog : env.frogs) {
System.out.print(frog.energy + ",");
}
System.out.println();
try {
List<Egg> newEggs = new ArrayList<Egg>();
for (int i = 0; i < env.frogs.size() / 10; i++)
newEggs.add(env.frogs.get(i).layEgg());
if (JSON_FILE_FORMAT) {
String newEggsString = JSON.toJSONString(newEggs);
FrogFileUtils.writeFile(Application.CLASSPATH + "eggs.json", newEggsString, "utf-8");
} else {
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(newEggs);
so.close();
}
env.eggs = newEggs;
System.out
.println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser" + "'");
} catch (IOException e) {
System.out.println(e);
}
}
private static void sortFrogsOrderByEnergyDesc(Env env) {
Collections.sort(env.frogs, new Comparator<Frog>() {
public int compare(Frog a, Frog b) {
if (a.energy >= b.energy)
return -1;
else
return 1;
}
});
}
/**
* 从磁盘读入一批Egg
*/
@SuppressWarnings("unchecked")
public static void loadEggs(Env env) {
boolean errorfound = false;
if (JSON_FILE_FORMAT) {
String eggsString = FrogFileUtils.readFile(Application.CLASSPATH + "eggs.json", "utf-8");
if (eggsString != null) {
List<JSONObject> jsonEggs = (List<JSONObject>) JSON.parse(eggsString);
env.eggs = new ArrayList<Egg>();
for (JSONObject json : jsonEggs) {
Egg egg = json.toJavaObject(Egg.class);
env.eggs.add(egg);
}
System.out.println(
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.json" + "'.");
} else
errorfound = true;
} else {
try {
FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser");
ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile);
env.eggs = (List<Egg>) eggsInputStream.readObject();
System.out.println(
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.");
eggsInputStream.close();
} catch (Exception e) {
errorfound = true;
e.printStackTrace();
}
}
if (errorfound) {
System.out.println("No eggs files ' " + Application.CLASSPATH + " found, created " + env.EGG_QTY
+ " new eggs to do test.");
env.eggs = new ArrayList<Egg>();
for (int i = 0; i < env.EGG_QTY; i++)
env.eggs.add(Egg.createBrandNewEgg());
}
}
}

View File

@ -0,0 +1,136 @@
/* Copyright 2018-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* File Utilities usually used inside of compiler
*
* @author Yong Zhu
* @since 1.0.0
*/
public class FrogFileUtils {
private FrogFileUtils() {
// default constructor
}
public static void writeFile(String fileFullPath, byte[] byteArry) {
File file = new File(fileFullPath);
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(byteArry);
fos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
try {
fos.flush();
} catch (Exception e) {
}
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void writeFile(String fileFullPath, String text, String encoding) {
File file = new File(fileFullPath);
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
byte[] bytes;
bytes = text.getBytes(encoding);
fos.write(bytes);
fos.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
try {
fos.flush();
} catch (Exception e) {
}
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static String readFile(String fileFullPath, String encoding) {
InputStream inputStream;
try {
inputStream = new FileInputStream(new File(fileFullPath));
} catch (FileNotFoundException e1) {
return null;
}
try {
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1)
result.write(buffer, 0, length);
String string = result.toString(encoding);
return string;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
public static void appendFile(String fileName, String content) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(fileName, true);
fos.write(content.getBytes());
fos.write("\r\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
try {
fos.flush();
} catch (Exception e) {
}
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

1
eggs.json Normal file

File diff suppressed because one or more lines are too long

BIN
eggs.ser Normal file

Binary file not shown.

BIN
frog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB