Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Next prod version? #21

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ tasks:
cargo install cargo-make
- stable: |
cd backend/
cargo make test
cargo make build-config-and-test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
Cargo.lock
hackagotchi.csv

/hcor
/config

/stead
/slack
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ futures-channel = "0.3.5"

[dependencies.hcor]
git = "https://github.com/hackagotchi/hcor.git"
branch = "slim"
branch = "staging"
# path = "../hcor"
features = [ "message_derive" ]
34 changes: 33 additions & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,38 @@ args = ["test", "--all-features"]

[tasks.test]
clear = true
env = { "SERVER_URL" = "http://localhost:8000", "UPDATES_PER_SECOND" = 10000 }
env = { SERVER_URL = "http://localhost:8000", UPDATES_PER_SECOND = 1000, NO_CLIENT_TIMEOUT = 30 }
dependencies = ["build-test-server"]
run_task = { name = ["run-test-server", "test-against-server"], parallel = true }

[tasks.build-config-and-test]
dependencies = [ "config" ]
env = { "CONFIG_PATH" = "./config" }
run_task = { name = ["test"], parallel = true }

[tasks.clean-hcor]
ignore_errors = true
command = "rm"
args = [ "-rf", "./hcor" ]

[tasks.clean-config]
ignore_errors = true
command = "rm"
args = [ "-rf", "./config" ]

[tasks.build-config]
command = "cargo"
args = [ "r", "--bin", "verify", "--features=config_verify" ]

[tasks.config]
script_runner = "@shell"
script = [
'''
git clone https://github.com/hackagotchi/config.git --branch staging
git clone https://github.com/hackagotchi/hcor.git --branch staging
cd hcor
cargo r --bin verify --features=config_verify
export CONFIG_PATH=./config
'''
]
dependencies = [ "clean-config", "clean-hcor" ]
105 changes: 56 additions & 49 deletions src/from_csv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Dumps a CSV file of the old dynamodb format into the db.
//! input CSVs are assumed to be generated with this tool: https://pypi.org/project/export-dynamodb/
use hcor::{item, ItemId, TileId};
use hcor::{item, Item, ItemId, TileId};
use serde::{Deserialize, Serialize};

/* To make the errors bearable.
Expand Down Expand Up @@ -101,8 +101,9 @@ fn as_json<D: serde::de::DeserializeOwned>(s: &str) -> Result<D, String> {
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use chrono::{DateTime, Utc};
use hcor::Hackstead;
use hcor::{item, plant, Hackstead};
use std::collections::HashMap;
use std::fs;

pretty_env_logger::init();

Expand All @@ -111,6 +112,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.map_err(|e| format!("invalid csv: {}", e))?;
let mut hacksteads: HashMap<String, (Hackstead, bool)> = HashMap::new();

let item_rows_to_uuids: HashMap<usize, item::Conf> = serde_json::from_str(
&fs::read_to_string(&format!(
"{}/item_row_numbers_to_uuids.json",
&*hcor::config::CONFIG_PATH
))
.unwrap(),
)
.unwrap();
let plant_rows_to_uuids: HashMap<usize, plant::Conf> = serde_json::from_str(
&fs::read_to_string(&format!(
"{}/plant_row_numbers_to_uuids.json",
&*hcor::config::CONFIG_PATH
))
.unwrap(),
)
.unwrap();

fn parse_date_time(dt: String) -> DateTime<Utc> {
DateTime::parse_from_str(&format!("{} +0000", dt), "%Y-%m-%dT%H:%M:%S%.fZ %z")
.unwrap_or_else(|e| panic!("couldn't parse dt {}: {}", dt, e))
Expand Down Expand Up @@ -147,27 +165,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
*found_profile = true;
}
1 | 2 => {
let archetype_handle = r.archetype_handle.expect("item no archetype");
let archetype_handle = r.archetype_handle.expect("item no archetype") as usize;
let item_id = ItemId(uuid::Uuid::parse_str(&r.id).expect("item id not uuid"));
hs.inventory.push(item::Item {
item_id,
owner_id: hs.profile.steader_id,
archetype_handle: archetype_handle as usize,
gotchi: if let (Some(nickname), Some(_)) = (r.nickname, r.harvest_log) {
Some(item::Gotchi { nickname })
} else {
None
},
ownership_log: vec![item::LoggedOwner {
logged_owner_id: hs.profile.steader_id,
acquisition: item::Acquisition::Trade,
owner_index: 0,
}],
})
let conf = item_rows_to_uuids[&archetype_handle];
let mut item =
Item::from_conf(conf, hs.profile.steader_id, item::Acquisition::Trade);
item.item_id = item_id;
if let (Some(nickname), Ok(g)) = (r.nickname, item.gotchi_mut()) {
g.nickname = nickname;
}
hs.inventory.push(item);
}
3 => {
use hcor::plant::{Craft, Effect};

#[derive(serde::Serialize, serde::Deserialize)]
struct OldPlant {
pub xp: usize,
Expand All @@ -191,16 +200,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
pub item_archetype_handle: usize,
pub effect_archetype_handle: usize,
}
impl std::ops::Deref for OldPlant {
type Target = hcor::config::PlantArchetype;

fn deref(&self) -> &Self::Target {
&hcor::config::CONFIG
.plant_archetypes
.get(self.archetype_handle as usize)
.expect("invalid archetype handle")
}
}

let acquired = r.acquired.expect("tiles need acquired dates");
let tile_id = TileId(uuid::Uuid::parse_str(&r.id).expect("tile id not uuid"));
Expand All @@ -213,25 +212,33 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
acquired: parse_date_time(acquired),
tile_id,
owner_id: hs.profile.steader_id,
plant: p.map(|p| hcor::Plant {
xp: p.xp,
owner_id: hs.profile.steader_id,
archetype_handle: p.archetype_handle,
nickname: p.name.clone(),
tile_id,
lifetime_rubs: p.effects.len(),
effects: p
.effects
.into_iter()
.map(|e| Effect {
effect_id: hcor::plant::EffectId(uuid::Uuid::new_v4()),
effect_archetype_handle: e.effect_archetype_handle,
item_archetype_handle: e.item_archetype_handle,
})
.collect(),
craft: p.craft.map(|c| Craft {
recipe_archetype_handle: c.recipe_archetype_handle,
}),
plant: p.map(|p| {
let conf = plant_rows_to_uuids[&p.archetype_handle];
hcor::Plant {
owner_id: hs.profile.steader_id,
conf,
nickname: conf.name.clone(),
tile_id,
lifetime_rubs: p.effects.len(),
skills: {
let mut skills = plant::Skills::new(conf);
skills.xp = p.xp;
skills
},
rub_effects: p
.effects
.into_iter()
.filter(|e| e.effect_archetype_handle == 0)
.flat_map(|e| {
plant::RubEffect::item_on_plant(
item_rows_to_uuids[&e.item_archetype_handle],
conf,
)
.into_iter()
})
.collect(),
craft: None,
}
}),
})
}
Expand Down
10 changes: 4 additions & 6 deletions src/hackstead/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@ fn user_path(iu: impl IdentifiesUser) -> String {
}

fn stead_path(is: impl IdentifiesSteader) -> String {
format!("stead/{}.json", is.steader_id())
format!("stead/{}.bincode", is.steader_id())
}

fn slack_path(slack: &str) -> String {
format!("slack/{}.json", slack)
format!("slack/{}.bincode", slack)
}

pub fn fs_get_stead(user_id: impl IdentifiesUser) -> Result<Hackstead, ServiceError> {
Ok(serde_json::from_str(&fs::read_to_string(user_path(
user_id,
))?)?)
Ok(bincode::deserialize(&fs::read(user_path(user_id))?)?)
}

pub fn fs_put_stead(hs: &Hackstead) -> Result<(), ServiceError> {
let stead_path = stead_path(hs);
fs::write(&stead_path, serde_json::to_string(hs)?)?;
fs::write(&stead_path, bincode::serialize(hs)?)?;

if let Some(s) = hs.profile.slack_id.as_ref() {
fs::hard_link(&stead_path, &slack_path(s))?;
Expand Down
92 changes: 44 additions & 48 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,51 +194,49 @@
//! # use uuid::Uuid;
//! # use hcor::{
//! # id::{SteaderId, ItemId},
//! # item::{Acquisition, Item, LoggedOwner},
//! # wormhole::{AskedNote::ItemHatchResult, Note, AskMessage}
//! # item::{self, Item, LoggedOwner},
//! # wormhole::{AskedNote::ItemHatchResult, Note, AskMessage},
//! # config::evalput::Output,
//! # };
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let item_id = ItemId(Uuid::new_v4());
//! # let owner_id = SteaderId(Uuid::new_v4());
//! assert_eq!(
//! serde_json::from_value::<Note>(json!({
//! "Asked": {
//! "ask_id": 1337,
//! "note": { "ItemHatchResult": {
//! "Ok": [
//! {
//! "item_id": item_id,
//! "owner_id": owner_id,
//! "archetype_handle": 5,
//! "Ok": {
//! "xp": 0,
//! "items": [{
//! "item_id": "ff8e2ac7-7c8c-4cbc-973e-d1e278f1096a",
//! "owner_id": "1776527a-7d0c-4384-a427-df556d0e9294",
//! // Confs show where in the config to look for more info.
//! "conf": "9845a8fb-5697-45ca-b9de-c34a26d59bd2",
//! "ownership_log": [
//! {
//! "logged_owner_id": owner_id,
//! "logged_owner_id": "1776527a-7d0c-4384-a427-df556d0e9294",
//! "acquisition": "Farmed",
//! "owner_index": 0,
//! }
//! ]
//! }
//! ]
//! }]
//! }
//! }}
//! }
//! }))?,
//! Note::Asked {
//! ask_id: 1337,
//! note: ItemHatchResult(Ok(vec![
//! Item {
//! item_id,
//! owner_id,
//! archetype_handle: 5,
//! gotchi: None,
//! ownership_log: vec![
//! LoggedOwner {
//! logged_owner_id: owner_id,
//! owner_index: 0,
//! acquisition: Acquisition::Farmed
//! }
//! ]
//! }
//! ]))
//! note: ItemHatchResult(Ok(Output {
//! xp: 0,
//! items: vec![{
//! let mut item = Item::from_conf(
//! hcor::CONFIG.item_named("Warp Powder").unwrap().conf,
//! SteaderId(Uuid::parse_str("1776527a-7d0c-4384-a427-df556d0e9294")?),
//! item::Acquisition::Farmed,
//! );
//! item.item_id = ItemId(Uuid::parse_str("ff8e2ac7-7c8c-4cbc-973e-d1e278f1096a")?);
//! item
//! }]
//! }))
//! }
//! );
//! // or perhaps the Ask fails,
Expand Down Expand Up @@ -339,27 +337,26 @@
//! ```
//! # use uuid::Uuid;
//! # use serde_json::json;
//! # use hcor::{id::TileId, plant, wormhole::{Note, RudeNote::RubEffectFinish}};
//! # use hcor::{id::TileId, plant::{self, RubEffectId}, wormhole::{Note, RudeNote::RubEffectFinish}};
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let tile_id = TileId(Uuid::new_v4());
//! # let effect_id = plant::EffectId(Uuid::new_v4());
//! assert_eq!(
//! serde_json::from_value::<Note>(json!({
//! "Rude": { "RubEffectFinish": {
//! "tile_id": tile_id,
//! "tile_id": "fb5e9693-650f-432c-bc9a-4f4b980a80fe",
//! "effect": {
//! "effect_id": effect_id,
//! "item_archetype_handle": 5,
//! "effect_archetype_handle": 0,
//! "effect_id": "bcf3d635-dae5-4785-9319-dd1739988320",
//! "item_conf": "9845a8fb-5697-45ca-b9de-c34a26d59bd2",
//! // It's possible to receive multiple effects from a single item; which is this?
//! "effect_index": 0,
//! }
//! }}
//! }))?,
//! Note::Rude(RubEffectFinish {
//! tile_id,
//! effect: plant::Effect {
//! effect_id,
//! item_archetype_handle: 5,
//! effect_archetype_handle: 0,
//! tile_id: TileId(Uuid::parse_str("fb5e9693-650f-432c-bc9a-4f4b980a80fe")?),
//! effect: plant::RubEffect {
//! effect_id: RubEffectId(Uuid::parse_str("bcf3d635-dae5-4785-9319-dd1739988320")?),
//! item_conf: hcor::CONFIG.item_named("Warp Powder").unwrap().conf,
//! effect_index: 0,
//! }
//! })
//! );
Expand Down Expand Up @@ -394,8 +391,6 @@
//! # use serde_json::json;
//! # use hcor::{id::TileId, plant, wormhole::{Note, EditNote}};
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let tile_id = TileId(Uuid::new_v4());
//! # let effect_id = plant::EffectId(Uuid::new_v4());
//! assert_eq!(
//! serde_json::from_value::<Note>(json!({
//! "Edit": { "Json":
Expand Down Expand Up @@ -445,7 +440,7 @@
#![allow(clippy::many_single_char_names)]
//#![forbid(missing_docs)]
#![forbid(unsafe_code)]
#![forbid(intra_doc_link_resolution_failure)]
#![forbid(broken_intra_doc_links)]
use actix_web::{error::ResponseError, HttpResponse};
use log::*;
use std::fmt;
Expand Down Expand Up @@ -547,6 +542,13 @@ impl From<serde_json::Error> for ServiceError {
}
}

impl From<bincode::Error> for ServiceError {
fn from(e: bincode::Error) -> ServiceError {
error!("bincode error: {}", e);
ServiceError::InternalServerError
}
}

impl From<std::io::Error> for ServiceError {
fn from(e: std::io::Error) -> ServiceError {
error!("io error: {}", e);
Expand All @@ -563,9 +565,3 @@ impl From<actix::MailboxError> for ServiceError {
ServiceError::InternalServerError
}
}

impl From<hcor::ConfigError> for ServiceError {
fn from(e: hcor::ConfigError) -> ServiceError {
ServiceError::bad_request(&e)
}
}
Loading