1
0
mirror of https://git.ngram.ca/OpenJam/rc-servers synced 2026-08-23 23:08:52 +00:00

rc_society dashboard display (#131)

### Description

Closes #130

### Please confirm

- [x] I am the legal owner or represent the legal owner of all work submitted (including LLM-generated code, if any)
- [x] I consent to my changes being added to this FOSS project
- [x] I have confirmed that this does not add new errors or warnings with `utils/clippy.sh`
- [ ] This PR used LLMs to generate some or all of the code changes

Reviewed-on: https://git.ngram.ca/OpenJam/rc-servers/pulls/131
This commit is contained in:
NG (Graham)
2026-06-20 21:48:09 +00:00
committed by NGnius
parent d2626bb47f
commit b597e1337d
19 changed files with 741 additions and 109 deletions

View File

@@ -66,6 +66,79 @@ impl ArcAdapter {
serde_json::to_string(&str_map).unwrap_or_else(|_| "{}".to_string())
}
fn listquery_to_db(&self, query: &libfj::robocraft::ListQuery) -> sea_orm::Select<super::entities::robot_metadata::Entity> {
let mut query_builder = super::entities::robot_metadata::Entity::find();
match query.order {
libfj::robocraft::FactoryOrderType::Suggested => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::RentCount); },
libfj::robocraft::FactoryOrderType::CombatRating => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::CombatRating); },
libfj::robocraft::FactoryOrderType::CosmeticRating => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::CosmeticRating); },
libfj::robocraft::FactoryOrderType::Added => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::AddedDate); },
libfj::robocraft::FactoryOrderType::CPU => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::Cpu); },
libfj::robocraft::FactoryOrderType::MostBought => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::BuyCount); },
}
if !query.text_filter.is_empty() {
let query_text = format!("%{}%", query.text_filter.replace('%', ""));
if query.player_filter {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text))
);
} else {
match query.text_search_field {
libfj::robocraft::FactoryTextSearchField::All => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::Name.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::Description.like(query_text))
);
},
libfj::robocraft::FactoryTextSearchField::Name => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::Name.like(query_text.clone()))
);
},
libfj::robocraft::FactoryTextSearchField::Player => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text))
);
},
}
}
}
if query.buyable {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedDate.lt("2025-01-23"))
.add(super::entities::robot_metadata::Column::Buyable.eq(1))
);
}
if query.featured_only {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Featured.eq(1));
}
// movement filters not supported
// weapon filters not supported
if query.minimum_cpu > 0 {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Cpu.gte(query.minimum_cpu as u32));
}
if query.maximum_cpu < usize::MAX {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Cpu.lte(query.maximum_cpu as u32));
}
if !self.ignore_expiry {
let now_str = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true).trim_end_matches('Z').to_owned();
log::debug!("Expiry must exceed `{}`", now_str);
query_builder = query_builder.filter(super::entities::robot_metadata::Column::ExpiryDate.gte(now_str))
}
query_builder
}
}
#[async_trait::async_trait]
@@ -115,76 +188,7 @@ impl crate::VehicleFactoryAdapter for ArcAdapter {
async fn list(&self, query: libfj::robocraft::ListQuery) -> Result<Vec<crate::VehicleQueryInfo>, Box<dyn std::error::Error>> {
log::debug!("Search vehicles with query {:?}", query);
let mut query_builder = super::entities::robot_metadata::Entity::find();
match query.order {
libfj::robocraft::FactoryOrderType::Suggested => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::RentCount); },
libfj::robocraft::FactoryOrderType::CombatRating => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::CombatRating); },
libfj::robocraft::FactoryOrderType::CosmeticRating => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::CosmeticRating); },
libfj::robocraft::FactoryOrderType::Added => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::AddedDate); },
libfj::robocraft::FactoryOrderType::CPU => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::Cpu); },
libfj::robocraft::FactoryOrderType::MostBought => { query_builder = query_builder.order_by_desc(super::entities::robot_metadata::Column::BuyCount); },
}
if !query.text_filter.is_empty() {
let query_text = format!("%{}%", query.text_filter.replace('%', ""));
if query.player_filter {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text))
);
} else {
match query.text_search_field {
libfj::robocraft::FactoryTextSearchField::All => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::Name.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::Description.like(query_text))
);
},
libfj::robocraft::FactoryTextSearchField::Name => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::Name.like(query_text.clone()))
);
},
libfj::robocraft::FactoryTextSearchField::Player => {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedBy.like(query_text.clone()))
.add(super::entities::robot_metadata::Column::AddedByDisplayName.like(query_text))
);
},
}
}
}
if query.buyable {
query_builder = query_builder.filter(
sea_orm::sea_query::Condition::any()
.add(super::entities::robot_metadata::Column::AddedDate.lt("2025-01-23"))
.add(super::entities::robot_metadata::Column::Buyable.eq(1))
);
}
if query.featured_only {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Featured.eq(1));
}
// movement filters not supported
// weapon filters not supported
if query.minimum_cpu > 0 {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Cpu.gte(query.minimum_cpu as u32));
}
if query.maximum_cpu < usize::MAX {
query_builder = query_builder.filter(super::entities::robot_metadata::Column::Cpu.lte(query.maximum_cpu as u32));
}
if !self.ignore_expiry {
let now_str = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true).trim_end_matches('Z').to_owned();
log::debug!("Expiry must exceed `{}`", now_str);
query_builder = query_builder.filter(super::entities::robot_metadata::Column::ExpiryDate.gte(now_str))
}
let query_params = query_builder;
let query_params = self.listquery_to_db(&query);
// FIXME add support for query.prepend_featured_bot
let metadata_pages = query_params.paginate(&self.orm, query.page_size as u64);
@@ -230,6 +234,14 @@ impl crate::VehicleFactoryAdapter for ArcAdapter {
Ok(infos)
}
async fn count(&self, query: libfj::robocraft::ListQuery) -> Result<usize, Box<dyn std::error::Error>> {
log::debug!("Count vehicles with query {:?}", query);
let query_params = self.listquery_to_db(&query);
query_params.count(&self.orm).await
.map(|len| len as usize)
.map_err(|e| Box::new(e) as _)
}
async fn upload(&self, vehicle: crate::VehicleUploadInfo) -> Result<crate::VehicleThumbnailInfo, Box<dyn std::error::Error>> {
if self.is_readonly {
return Ok(crate::VehicleThumbnailInfo {

View File

@@ -2,6 +2,11 @@
pub trait VehicleFactoryAdapter: Send + Sync + 'static {
async fn vehicle(&self, id: i32) -> Result<Option<(VehicleInfo, VehicleQueryInfo)>, Box<dyn std::error::Error>>;
async fn list(&self, query: libfj::robocraft::ListQuery) -> Result<Vec<VehicleQueryInfo>, Box<dyn std::error::Error>>;
// used by society web dashboard
async fn count(&self, query: libfj::robocraft::ListQuery) -> Result<usize, Box<dyn std::error::Error>> {
Ok(self.list(query).await?.len())
}
async fn upload(&self, vehicle: VehicleUploadInfo) -> Result<VehicleThumbnailInfo, Box<dyn std::error::Error>>;
async fn rate_vehicle(&self, id: i32, combat: i32, cosmetic: i32) -> Result<(), Box<dyn std::error::Error>>;
/// Just update any purchase trackers