325 lines
9.7 KiB
Rust
325 lines
9.7 KiB
Rust
use std::f64;
|
|
use std::fs::copy;
|
|
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
use std::char::from_u32;
|
|
|
|
use uuid::Uuid;
|
|
use rand::prelude::*;
|
|
use rand::distributions::{Normal, WeightedIndex};
|
|
|
|
use failure::Error;
|
|
use failure::err_msg;
|
|
|
|
pub fn molecular_write(id: Uuid) -> Result<Uuid, Error> {
|
|
let mut rng = thread_rng();
|
|
|
|
for _i in 0..100 {
|
|
let mol: u32 = rng.gen_range(0, 10000);
|
|
let src = format!("/var/lib/mnml/data/molecules/{}.svg", mol);
|
|
let dest = format!("/var/lib/mnml/public/imgs/{}.svg", id);
|
|
debug!("molecule src={:?}", src);
|
|
debug!("molecule dest={:?}", dest);
|
|
if let Ok(_bytes) = copy(&src, &dest) {
|
|
info!("new molecule img generated src={:?} dest={:?}", src, dest);
|
|
return Ok(id);
|
|
}
|
|
}
|
|
|
|
return Err(err_msg("too many missing molecules. wrong directory?"))
|
|
}
|
|
|
|
pub fn invader_write(id: Uuid) -> Result<Uuid, Error> {
|
|
let mut rng = thread_rng();
|
|
let mut svg = Vec::new();
|
|
|
|
// rounding ?
|
|
// filters ?
|
|
|
|
// distribution for lightness
|
|
// bellcurve around 75%
|
|
let l_dist = Normal::new(75.0, 10.0);
|
|
let s_dist = Normal::new(25.0, 10.0);
|
|
|
|
let mut colours = std::iter
|
|
::repeat_with(|| {
|
|
let h = rng.gen_range(0, 360);
|
|
let s = s_dist.sample(&mut rng) as usize;
|
|
let l = l_dist.sample(&mut rng) as usize;
|
|
format!("hsl({:}, {:}%, {:}%)", h, s, l)
|
|
})
|
|
.take(3)
|
|
.collect::<Vec<String>>();
|
|
|
|
colours.push("none".to_string());
|
|
|
|
// add up to 100 for %
|
|
let weights = [
|
|
5,
|
|
5,
|
|
65,
|
|
25, // the transparent colour
|
|
];
|
|
let colour_dist = WeightedIndex::new(&weights)?;
|
|
|
|
write!(&mut svg, "<svg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='-250 -250 1000 1000' width='375' height='375'><g>")?;
|
|
for i in 0..50 {
|
|
let x = (i % 5) * 50;
|
|
let y = (i / 5) * 50;
|
|
|
|
let colour = &colours[colour_dist.sample(&mut rng)];
|
|
|
|
write!(&mut svg, "<rect fill=\"{}\" x=\"{}\" y=\"{}\" width=\"50\" height=\"50\" />", colour, x, y)?;
|
|
write!(&mut svg, "<rect fill=\"{}\" x=\"{}\" y=\"{}\" width=\"50\" height=\"50\" />", colour, 450 - x, y)?;
|
|
}
|
|
|
|
write!(&mut svg, "</g></svg>")?;
|
|
|
|
let dest = format!("/var/lib/mnml/public/imgs/{}.svg", id);
|
|
println!("molecule dest={:?}", dest);
|
|
|
|
let mut file = File::create(dest)?;
|
|
file.write_all(&svg)?;
|
|
|
|
Ok(id)
|
|
}
|
|
|
|
enum ConstructShape {
|
|
Square,
|
|
Triangle,
|
|
Circle,
|
|
Line,
|
|
V,
|
|
Tri,
|
|
Plus,
|
|
Blank,
|
|
}
|
|
|
|
// default ? shape
|
|
pub fn construct(id: Uuid) -> Result<Uuid, Error> {
|
|
let mut rng = thread_rng();
|
|
let mut svg = Vec::new();
|
|
|
|
// distribution for lightness
|
|
// bellcurve around 75%
|
|
let l_dist = Normal::new(50.0, 10.0);
|
|
let s_dist = Normal::new(25.0, 10.0);
|
|
|
|
// 8 6 or 4 points in shape
|
|
// 1 head point
|
|
// n / 2 shapes with a colour each
|
|
// random size/radius props for each
|
|
|
|
// add up to 100 for %
|
|
let shapes = [
|
|
(ConstructShape::Square, 100),
|
|
// (ConstructShape::Triangle, 10),
|
|
// (ConstructShape::Circle, 10),
|
|
// (ConstructShape::Line, 10),
|
|
// (ConstructShape::V, 10),
|
|
// (ConstructShape::Tri, 3),
|
|
// (ConstructShape::Plus, 5),
|
|
// (ConstructShape::Blank, 1),
|
|
];
|
|
let shape_dist = WeightedIndex::new(shapes.iter().map(|v| v.1))?;
|
|
|
|
let n_shapes = rng.gen_range(2, 10);
|
|
|
|
write!(&mut svg, "<svg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='-500 -500 1000 1000' width='1000' height='1000'><g>")?;
|
|
for i in 0..n_shapes - 1 {
|
|
let h = rng.gen_range(0, 360);
|
|
let s = s_dist.sample(&mut rng) as usize;
|
|
let l = l_dist.sample(&mut rng) as usize;
|
|
let colour = format!("hsl({:}, {:}%, {:}%)", h, s, l);
|
|
|
|
let fraction: f64 = (1.0 / n_shapes as f64) * i as f64;
|
|
let angle: f64 = (fraction * 180.0) / f64::consts::PI;
|
|
|
|
match shapes[shape_dist.sample(&mut rng)].0 {
|
|
ConstructShape::Square => {
|
|
let size = rng.gen_range(5, 50);
|
|
let distance = rng.gen_range(50, 200);
|
|
let rotation = rng.gen_range(0, 180);
|
|
write!(&mut svg, "<rect fill=\"{}\" x=\"-{}\" y=\"{}\" width=\"{}\" height=\"{}\" transform=\"rotate({}) translate(0, {}) rotate({})\" />",
|
|
colour, size / 2, size / 2, size, size, rotation, distance, angle)?;
|
|
write!(&mut svg, "<rect fill=\"{}\" x=\"-{}\" y=\"{}\" width=\"{}\" height=\"{}\" transform=\"rotate({}) translate(0, {}) rotate({})\" />",
|
|
colour, size / 2, size / 2, size, size, rotation, distance, angle + 180.0)?;
|
|
},
|
|
ConstructShape::Triangle => {
|
|
|
|
},
|
|
ConstructShape::Circle => {
|
|
|
|
},
|
|
ConstructShape::Line => {
|
|
|
|
},
|
|
ConstructShape::V => {
|
|
|
|
},
|
|
ConstructShape::Tri => {
|
|
|
|
},
|
|
ConstructShape::Plus => {
|
|
|
|
},
|
|
ConstructShape::Blank => {
|
|
|
|
},
|
|
}
|
|
}
|
|
|
|
write!(&mut svg, "</g></svg>")?;
|
|
|
|
let dest = format!("/var/lib/mnml/public/imgs/{}.svg", id);
|
|
println!("default dest={:?}", dest);
|
|
|
|
let mut file = File::create(dest)?;
|
|
file.write_all(&svg)?;
|
|
|
|
Ok(id)
|
|
}
|
|
|
|
|
|
fn _hieroglyph() -> String {
|
|
let mut rng = thread_rng();
|
|
|
|
let mut s = String::new();
|
|
for i in 0..4 {
|
|
s.push(from_u32(rng.gen_range(0x13000, 0x1342E)).unwrap());
|
|
if i == 1 {
|
|
// newline
|
|
s.push(from_u32(0x000a).unwrap());
|
|
}
|
|
}
|
|
|
|
// println!("{:}", s);
|
|
return s;
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
// #[test]
|
|
// fn invader_img_test() {
|
|
// for i in 0..100 {
|
|
// invader_img_write(Uuid::new_v4()).unwrap();
|
|
// }
|
|
// }
|
|
|
|
// #[test]
|
|
// fn hieroglyph_test() {
|
|
// hieroglyph();
|
|
// }
|
|
|
|
#[test]
|
|
fn construct_img_test() {
|
|
for i in 0..100 {
|
|
construct(Uuid::new_v4()).unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// function createColor() {
|
|
// //saturation is the whole color spectrum
|
|
// var h = Math.floor(rand() * 360);
|
|
// //saturation goes from 40 to 100, it avoids greyish colors
|
|
// var s = ((rand() * 60) + 40) + '%';
|
|
// //lightness can be anything from 0 to 100, but probabilities are a bell curve around 75%
|
|
// var l = ((rand()+rand()+rand()+rand()) * 25) + '%';
|
|
|
|
// var color = 'hsl(' + h + ',' + s + ',' + l + ')';
|
|
// return color;
|
|
// }
|
|
|
|
// function createImageData(size) {
|
|
// var width = size; // Only support square icons for now
|
|
// var height = size;
|
|
|
|
// var dataWidth = Math.ceil(width / 2);
|
|
// var mirrorWidth = width - dataWidth;
|
|
|
|
// var data = [];
|
|
// for(var y = 0; y < height; y++) {
|
|
// var row = [];
|
|
// for(var x = 0; x < dataWidth; x++) {
|
|
// // this makes foreground and background color to have a 43% (1/2.3) probability
|
|
// // spot color has 13% chance
|
|
// row[x] = Math.floor(rand()*2.3);
|
|
// }
|
|
// var r = row.slice(0, mirrorWidth);
|
|
// r.reverse();
|
|
// row = row.concat(r);
|
|
|
|
// for(var i = 0; i < row.length; i++) {
|
|
// data.push(row[i]);
|
|
// }
|
|
// }
|
|
|
|
// return data;
|
|
// }
|
|
|
|
// function buildOpts(opts) {
|
|
// var newOpts = {};
|
|
|
|
// newOpts.seed = opts.seed || Math.floor((Math.random()*Math.pow(10,16))).toString(16);
|
|
|
|
// seedrand(newOpts.seed);
|
|
|
|
// newOpts.size = opts.size || 8;
|
|
// newOpts.scale = opts.scale || 4;
|
|
// newOpts.color = opts.color || createColor();
|
|
// newOpts.bgcolor = opts.bgcolor || createColor();
|
|
// newOpts.spotcolor = opts.spotcolor || createColor();
|
|
|
|
// return newOpts;
|
|
// }
|
|
// ],
|
|
// - _ => vec![
|
|
// - (ItemAction::RerollStamina, 1),
|
|
// - (ItemAction::RerollPhysDamage, 1),
|
|
// - (ItemAction::RerollSpellDamage, 1),
|
|
// - (ItemAction::RerollSpeed, 1),
|
|
// - (ItemAction::RerollArmour, 1),
|
|
// - (ItemAction::RerollSpellShield, 1),
|
|
// - (ItemAction::RerollEvasion, 1),
|
|
// - ],
|
|
// + // _ => vec![
|
|
// + // (ItemAction::RerollStamina, 1),
|
|
// + // (ItemAction::RerollPhysDamage, 1),
|
|
// + // (ItemAction::RerollSpellDamage, 1),
|
|
// + // (ItemAction::RerollSpeed, 1),
|
|
// + // (ItemAction::RerollArmour, 1),
|
|
// + // (ItemAction::RerollSpellShield, 1),
|
|
// + // (ItemAction::RerollEvasion, 1),
|
|
// + // ],
|
|
// }
|
|
// }
|
|
|
|
// -pub fn item_drop(tx: &mut Transaction, account_id: Uuid, mode: GameMode) -> Result<Item, Error> {
|
|
// +pub fn item_drop(tx: &mut Transaction, account_id: Uuid, mode: GameMode) -> Result<(), Error> {
|
|
// let mut rng = thread_rng();
|
|
|
|
// - let actions = mode_drops(mode);
|
|
// + let log_normal = LogNormal::new(1.0, 1.0);
|
|
// + let num_drops = log_normal.sample(&mut rng).floor() as usize;
|
|
// +
|
|
// + println!("{:?} drops", num_drops);
|
|
|
|
// - let dist = WeightedIndex::new(actions.iter().map(|item| item.1)).unwrap();
|
|
// - let kind = actions[dist.sample(&mut rng)].0;
|
|
// - let item = Item::new(kind, account_id);
|
|
// + for _i in 0..num_drops {
|
|
// + let actions = mode_drops(mode);
|
|
|
|
// - println!("{:?} dropped {:?}", account_id, item);
|
|
// + let dist = WeightedIndex::new(actions.iter().map(|item| item.1)).unwrap();
|
|
// + let kind = actions[dist.sample(&mut rng)].0;
|
|
// + let item = Item::new(kind, account_id);
|
|
|
|
// - return item_create(item, tx, account_id);
|
|
// + println!("{:?} dropped {:?}", account_id, item);
|
|
// + item_create(item, tx, account_id)?;V
|