use crate::db_object::{DBObject, OrderTypes};
use crate::df_world::{Coordinate, DBDFWorld};
use crate::schema::entities;
use crate::DbConnection;
use df_st_core::fillable::{Fillable, Filler};
use df_st_core::item_count::ItemCount;
use df_st_derive::{Fillable, HashAndPartialEqById};
use diesel::expression_methods::ExpressionMethods;
use diesel::prelude::*;
use diesel::query_dsl::RunQueryDsl;
use diesel::Queryable;
use failure::Error;
use std::collections::HashMap;
mod entity_child_en_id;
mod entity_hf_id;
mod entity_honor;
mod entity_link;
mod entity_occasion;
mod entity_occasion_schedule;
mod entity_occasion_schedule_feature;
mod entity_position;
mod entity_position_assignment;
mod entity_profession;
mod entity_weapon;
mod entity_worship_id;
pub use entity_child_en_id::EntityChildENID;
pub use entity_hf_id::EntityHFID;
pub use entity_honor::EntityHonor;
pub use entity_link::EntityLink;
pub use entity_occasion::EntityOccasion;
pub use entity_occasion_schedule::EntityOccasionSchedule;
pub use entity_occasion_schedule_feature::EntityOccasionScheduleFeature;
pub use entity_position::EntityPosition;
pub use entity_position_assignment::EntityPositionAssignment;
pub use entity_profession::EntityProfession;
pub use entity_weapon::EntityWeapon;
pub use entity_worship_id::EntityWorshipID;
#[derive(
Clone,
Debug,
AsChangeset,
Identifiable,
HashAndPartialEqById,
Queryable,
Insertable,
Fillable,
Default,
)]
#[table_name = "entities"]
pub struct Entity {
pub id: i32,
pub world_id: i32,
pub name: Option<String>,
pub race: Option<String>,
pub type_: Option<String>,
}
impl Entity {
pub fn new() -> Self {
Self::default()
}
}
impl DBObject<df_st_core::Entity, Entity> for Entity {
fn add_missing_data_advanced(core_world: &df_st_core::DFWorld, world: &mut DBDFWorld) {
for entity in core_world.entities.values() {
for honor in &entity.honor {
let mut df_honor = EntityHonor::new();
df_honor.add_missing_data(honor);
df_honor.en_id = entity.id;
world.entity_honors.push(df_honor);
}
for entity_link in &entity.entity_link {
let mut df_entity_link = EntityLink::new();
df_entity_link.add_missing_data(entity_link);
df_entity_link.en_id = entity.id;
world.entity_links.push(df_entity_link);
}
for entity_position in &entity.entity_position {
let mut df_entity_position = EntityPosition::new();
df_entity_position.add_missing_data(entity_position);
df_entity_position.en_id = entity.id;
world.entity_positions.push(df_entity_position);
}
for entity_position_assignment in &entity.entity_position_assignment {
let mut df_entity_position_assignment = EntityPositionAssignment::new();
df_entity_position_assignment.add_missing_data(entity_position_assignment);
df_entity_position_assignment.en_id = entity.id;
world
.entity_position_assignments
.push(df_entity_position_assignment);
}
for occasion in &entity.occasion {
let mut df_occasion = EntityOccasion::new();
df_occasion.add_missing_data(occasion);
df_occasion.en_id = entity.id;
world.entity_occasions.push(df_occasion);
for schedule in &occasion.schedule {
let mut df_entity_occasion_schedule = EntityOccasionSchedule::new();
df_entity_occasion_schedule.add_missing_data(schedule);
df_entity_occasion_schedule.en_id = entity.id;
df_entity_occasion_schedule.en_occ_id = occasion.local_id;
world
.entity_occasion_schedules
.push(df_entity_occasion_schedule);
for feature in &schedule.feature {
let mut df_feature = EntityOccasionScheduleFeature::new();
df_feature.add_missing_data(feature);
df_feature.en_id = entity.id;
df_feature.en_occ_id = occasion.local_id;
df_feature.en_occ_sch_id = schedule.local_id;
world.entity_occasion_schedule_features.push(df_feature);
}
}
}
for item in &entity.worship_id {
let mut db_item = EntityWorshipID::new();
db_item.en_id = entity.id;
db_item.worship_id = *item;
world.entity_worship_ids.push(db_item);
}
for item in &entity.weapon {
let mut db_item = EntityWeapon::new();
db_item.en_id = entity.id;
db_item.weapon = item.clone();
world.entity_weapons.push(db_item);
}
for item in &entity.profession {
let mut db_item = EntityProfession::new();
db_item.en_id = entity.id;
db_item.profession = item.clone();
world.entity_professions.push(db_item);
}
for item in &entity.hf_ids {
let mut db_item = EntityHFID::new();
db_item.en_id = entity.id;
db_item.hf_id = *item;
world.entity_hf_ids.push(db_item);
}
for item in &entity.child_en_ids {
let mut db_item = EntityChildENID::new();
db_item.en_id = entity.id;
db_item.child_en_id = *item;
world.entity_child_en_ids.push(db_item);
}
for coord in &entity.claims {
let new_id: i32 = world.coordinates.len() as i32;
world.coordinates.push(Coordinate {
id: new_id,
x: coord.x,
y: coord.y,
entity_id: Some(entity.id),
..Default::default()
});
}
}
}
#[cfg(feature = "postgres")]
fn insert_into_db(conn: &DbConnection, entities: &[Entity]) {
use diesel::pg::upsert::excluded;
diesel::insert_into(entities::table)
.values(entities)
.on_conflict((entities::id, entities::world_id))
.do_update()
.set((
entities::name.eq(excluded(entities::name)),
entities::race.eq(excluded(entities::race)),
entities::type_.eq(excluded(entities::type_)),
))
.execute(conn)
.expect("Error saving entities");
}
#[cfg(not(feature = "postgres"))]
fn insert_into_db(conn: &DbConnection, entities: &[Entity]) {
diesel::insert_into(entities::table)
.values(entities)
.execute(conn)
.expect("Error saving entities");
}
fn find_db_item(
conn: &DbConnection,
id_filter: HashMap<String, i32>,
) -> Result<Option<Entity>, Error> {
use crate::schema::entities::dsl::*;
let query = entities;
let query = query.filter(world_id.eq(id_filter.get("world_id").unwrap_or(&0)));
let query = query.filter(id.eq(id_filter.get("id").unwrap_or(&0)));
Ok(query.first::<Entity>(conn).optional()?)
}
fn find_db_list(
conn: &DbConnection,
id_filter: HashMap<String, i32>,
_string_filter: HashMap<String, String>,
offset: i64,
limit: i64,
order: Option<OrderTypes>,
order_by: Option<String>,
id_list: Option<Vec<i32>>,
) -> Result<Vec<Entity>, Error> {
use crate::schema::entities::dsl::*;
let (order_by, asc) = Self::get_order(order, order_by);
let query = entities.limit(limit).offset(offset);
let query = query.filter(world_id.eq(id_filter.get("world_id").unwrap_or(&0)));
optional_filter! {
query, id_filter,
id_list => id,
[
"id" => id,
],
{Ok(order_by!{
order_by, asc, query, conn,
"id" => id,
"name" => name,
"race" => race,
"type" => type_,
})},
}
}
fn match_field_by(field: String) -> String {
match field.as_ref() {
"name" => "name",
"race" => "race",
"type" => "type",
_ => "id",
}
.to_owned()
}
fn add_nested_items(
conn: &DbConnection,
db_list: &[Entity],
_core_list: Vec<df_st_core::Entity>,
) -> Result<Vec<df_st_core::Entity>, Error> {
let world_id = match db_list.first() {
Some(x) => x.world_id,
None => 0,
};
let honor_list = EntityHonor::belonging_to(db_list)
.filter(crate::schema::entity_honors::world_id.eq(world_id))
.load::<EntityHonor>(conn)?
.grouped_by(db_list);
let link_list = EntityLink::belonging_to(db_list)
.filter(crate::schema::entity_links::world_id.eq(world_id))
.load::<EntityLink>(conn)?
.grouped_by(db_list);
let pos_list = EntityPosition::belonging_to(db_list)
.filter(crate::schema::entity_positions::world_id.eq(world_id))
.load::<EntityPosition>(conn)?
.grouped_by(db_list);
let pos_assignment_list = EntityPositionAssignment::belonging_to(db_list)
.filter(crate::schema::entity_position_assignments::world_id.eq(world_id))
.load::<EntityPositionAssignment>(conn)?
.grouped_by(db_list);
let occasion_list = EntityOccasion::belonging_to(db_list)
.filter(crate::schema::entity_occasions::world_id.eq(world_id))
.load::<EntityOccasion>(conn)?
.grouped_by(db_list);
let schedule_list = EntityOccasionSchedule::belonging_to(db_list)
.filter(crate::schema::entity_occasion_schedules::world_id.eq(world_id))
.load::<EntityOccasionSchedule>(conn)?
.grouped_by(db_list);
let schedule_feature_list = EntityOccasionScheduleFeature::belonging_to(db_list)
.filter(crate::schema::entity_occasion_schedule_features::world_id.eq(world_id))
.load::<EntityOccasionScheduleFeature>(conn)?
.grouped_by(db_list);
let worship_id_list = EntityWorshipID::belonging_to(db_list)
.filter(crate::schema::entity_worship_ids::world_id.eq(world_id))
.load::<EntityWorshipID>(conn)?
.grouped_by(db_list);
let weapon_list = EntityWeapon::belonging_to(db_list)
.filter(crate::schema::entity_weapons::world_id.eq(world_id))
.load::<EntityWeapon>(conn)?
.grouped_by(db_list);
let profession_list = EntityProfession::belonging_to(db_list)
.filter(crate::schema::entity_professions::world_id.eq(world_id))
.load::<EntityProfession>(conn)?
.grouped_by(db_list);
let hf_id_list = EntityHFID::belonging_to(db_list)
.filter(crate::schema::entity_hf_ids::world_id.eq(world_id))
.load::<EntityHFID>(conn)?
.grouped_by(db_list);
let child_en_id_list = EntityChildENID::belonging_to(db_list)
.filter(crate::schema::entity_child_en_ids::world_id.eq(world_id))
.load::<EntityChildENID>(conn)?
.grouped_by(db_list);
let coord_list = Coordinate::belonging_to(db_list)
.filter(crate::schema::coordinates::world_id.eq(world_id))
.load::<Coordinate>(conn)?
.grouped_by(db_list);
let mut core_list: Vec<df_st_core::Entity> = Vec::new();
for (index, en) in db_list.iter().enumerate() {
let mut core_en = df_st_core::Entity::new();
core_en.add_missing_data(en);
for honor in honor_list.get(index).unwrap() {
core_en.honor.add_missing_data(&vec![honor.clone()]);
}
for link in link_list.get(index).unwrap() {
core_en.entity_link.add_missing_data(&vec![link.clone()]);
}
for pos in pos_list.get(index).unwrap() {
core_en.entity_position.add_missing_data(&vec![pos.clone()]);
}
for pos_assignment in pos_assignment_list.get(index).unwrap() {
core_en
.entity_position_assignment
.add_missing_data(&vec![pos_assignment.clone()]);
}
for occasion in occasion_list.get(index).unwrap() {
let en_occ_id = occasion.local_id;
let mut core_occasion = df_st_core::EntityOccasion::new();
core_occasion.add_missing_data(occasion);
for schedule in schedule_list.get(index).unwrap() {
if schedule.en_occ_id == en_occ_id {
let en_occ_sch_id = schedule.local_id;
let mut core_schedule = df_st_core::EntityOccasionSchedule::new();
core_schedule.add_missing_data(schedule);
for schedule_feature in schedule_feature_list.get(index).unwrap() {
if schedule_feature.en_occ_id == en_occ_id
&& schedule_feature.en_occ_sch_id == en_occ_sch_id
{
core_schedule
.feature
.add_missing_data(&vec![schedule_feature.clone()]);
}
}
core_occasion
.schedule
.add_missing_data(&vec![core_schedule]);
}
}
core_en.occasion.push(core_occasion);
}
for item in worship_id_list.get(index).unwrap() {
core_en.worship_id.push(item.worship_id);
}
for item in weapon_list.get(index).unwrap() {
core_en.weapon.push(item.weapon.clone());
}
for item in profession_list.get(index).unwrap() {
core_en.profession.push(item.profession.clone());
}
for item in hf_id_list.get(index).unwrap() {
core_en.hf_ids.push(item.hf_id);
}
for item in child_en_id_list.get(index).unwrap() {
core_en.child_en_ids.push(item.child_en_id);
}
core_en
.claims
.add_missing_data(coord_list.get(index).unwrap());
core_list.push(core_en);
}
Ok(core_list)
}
fn get_count_from_db(
conn: &DbConnection,
id_filter: HashMap<String, i32>,
_string_filter: HashMap<String, String>,
offset: u32,
limit: u32,
group_by_opt: Option<String>,
id_list: Option<Vec<i32>>,
) -> Result<Vec<ItemCount>, Error> {
use crate::schema::entities::dsl::*;
let query = entities.limit(limit as i64).offset(offset as i64);
let query = query.filter(world_id.eq(id_filter.get("world_id").unwrap_or(&0)));
optional_filter! {
query, id_filter,
id_list => id,
[
"id" => id,
],
{group_by!{
group_by_opt, query, conn,
"id" => {id: i32},
"name" => {name: Option<String>},
"race" => {race: Option<String>},
"type" => {type_: Option<String>},
};},
};
}
}
impl Filler<Entity, df_st_core::Entity> for Entity {
fn add_missing_data(&mut self, source: &df_st_core::Entity) {
self.id.add_missing_data(&source.id);
self.name.add_missing_data(&source.name);
self.race.add_missing_data(&source.race);
self.type_.add_missing_data(&source.type_);
}
}
impl Filler<df_st_core::Entity, Entity> for df_st_core::Entity {
fn add_missing_data(&mut self, source: &Entity) {
self.id.add_missing_data(&source.id);
self.name.add_missing_data(&source.name);
self.race.add_missing_data(&source.race);
self.type_.add_missing_data(&source.type_);
}
}
impl PartialEq<Entity> for df_st_core::Entity {
fn eq(&self, other: &Entity) -> bool {
self.id == other.id
}
}
impl PartialEq<df_st_core::Entity> for Entity {
fn eq(&self, other: &df_st_core::Entity) -> bool {
self.id == other.id
}
}