Refactor SQL queries into a dedicated module
- Moved SQL queries from multiple worker files into `src/worker/sql.rs` for better organization and maintainability. - Updated references in `stockage_manager.rs`, `transport.rs`, `underground.rs`, `user_character.rs`, and `value_recalculation.rs` to use the new centralized SQL queries. - Improved code readability by replacing `.get(0)` with `.first()` for better clarity when retrieving the first row from query results. - Cleaned up unnecessary comments and consolidated related SQL queries.
This commit is contained in:
@@ -6,291 +6,27 @@ use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use super::base::{BaseWorker, Worker, WorkerState};
|
||||
use crate::worker::sql::{
|
||||
QUERY_UPDATE_PRODUCT_KNOWLEDGE_USER,
|
||||
QUERY_DELETE_OLD_PRODUCTIONS,
|
||||
QUERY_GET_PRODUCERS_LAST_DAY,
|
||||
QUERY_UPDATE_REGION_SELL_PRICE,
|
||||
QUERY_DELETE_REGION_SELL_PRICE,
|
||||
QUERY_GET_SELL_REGIONS,
|
||||
QUERY_HOURLY_PRICE_RECALCULATION,
|
||||
QUERY_SET_MARRIAGES_BY_PARTY,
|
||||
QUERY_GET_STUDYINGS_TO_EXECUTE,
|
||||
QUERY_GET_OWN_CHARACTER_ID,
|
||||
QUERY_INCREASE_ONE_PRODUCT_KNOWLEDGE,
|
||||
QUERY_INCREASE_ALL_PRODUCTS_KNOWLEDGE,
|
||||
QUERY_SET_LEARNING_DONE,
|
||||
};
|
||||
|
||||
pub struct ValueRecalculationWorker {
|
||||
base: BaseWorker,
|
||||
}
|
||||
|
||||
// Produktwissen / Produktions-Logs
|
||||
const QUERY_UPDATE_PRODUCT_KNOWLEDGE_USER: &str = r#"
|
||||
UPDATE falukant_data.knowledge k
|
||||
SET knowledge = LEAST(100, k.knowledge + 1)
|
||||
FROM falukant_data.character c
|
||||
JOIN falukant_log.production p
|
||||
ON DATE(p.production_timestamp) = CURRENT_DATE - INTERVAL '1 day'
|
||||
WHERE c.id = k.character_id
|
||||
AND c.user_id = 18
|
||||
AND k.product_id = 10;
|
||||
"#;
|
||||
|
||||
const QUERY_DELETE_OLD_PRODUCTIONS: &str = r#"
|
||||
DELETE FROM falukant_log.production flp
|
||||
WHERE DATE(flp.production_timestamp) < CURRENT_DATE;
|
||||
"#;
|
||||
|
||||
const QUERY_GET_PRODUCERS_LAST_DAY: &str = r#"
|
||||
SELECT p.producer_id
|
||||
FROM falukant_log.production p
|
||||
WHERE DATE(p.production_timestamp) = CURRENT_DATE - INTERVAL '1 day'
|
||||
GROUP BY producer_id;
|
||||
"#;
|
||||
|
||||
// Regionale Verkaufspreise
|
||||
const QUERY_UPDATE_REGION_SELL_PRICE: &str = r#"
|
||||
UPDATE falukant_data.town_product_worth tpw
|
||||
SET worth_percent =
|
||||
GREATEST(
|
||||
0,
|
||||
LEAST(
|
||||
CASE
|
||||
WHEN s.quantity > avg_sells THEN tpw.worth_percent - 1
|
||||
WHEN s.quantity < avg_sells THEN tpw.worth_percent + 1
|
||||
ELSE tpw.worth_percent
|
||||
END,
|
||||
100
|
||||
)
|
||||
)
|
||||
FROM (
|
||||
SELECT region_id,
|
||||
product_id,
|
||||
quantity,
|
||||
(SELECT AVG(quantity)
|
||||
FROM falukant_log.sell avs
|
||||
WHERE avs.product_id = s.product_id) AS avg_sells
|
||||
FROM falukant_log.sell s
|
||||
WHERE DATE(s.sell_timestamp) = CURRENT_DATE - INTERVAL '1 day'
|
||||
) s
|
||||
WHERE tpw.region_id = s.region_id
|
||||
AND tpw.product_id = s.product_id;
|
||||
"#;
|
||||
|
||||
const QUERY_DELETE_REGION_SELL_PRICE: &str = r#"
|
||||
DELETE FROM falukant_log.sell s
|
||||
WHERE DATE(s.sell_timestamp) < CURRENT_DATE;
|
||||
"#;
|
||||
|
||||
const QUERY_GET_SELL_REGIONS: &str = r#"
|
||||
SELECT s.region_id
|
||||
FROM falukant_log.sell s
|
||||
WHERE DATE(s.sell_timestamp) = CURRENT_DATE - INTERVAL '1 day'
|
||||
GROUP BY region_id;
|
||||
"#;
|
||||
|
||||
// Stündliche Preisneuberechnung basierend auf Verkäufen der letzten Stunde
|
||||
// Zwei Ebenen der Preisberechnung:
|
||||
// 1. Weltweit: Vergleich Stadt-Verkäufe vs. weltweiter Durchschnitt
|
||||
// - ±5% Toleranz: Preis bleibt gleich
|
||||
// - Mehr Verkäufe (>5% über Durchschnitt): Preis +10%
|
||||
// - Weniger Verkäufe (<5% unter Durchschnitt): Preis -10%
|
||||
// 2. Parent-Region: Vergleich Stadt-Verkäufe vs. Durchschnitt der parent-region
|
||||
// - ±5% Toleranz: Preis bleibt gleich
|
||||
// - Abweichung >±5%: Preis ±5%
|
||||
const QUERY_HOURLY_PRICE_RECALCULATION: &str = r#"
|
||||
WITH city_sales AS (
|
||||
SELECT
|
||||
s.region_id,
|
||||
s.product_id,
|
||||
SUM(s.quantity) AS total_sold
|
||||
FROM falukant_log.sell s
|
||||
WHERE s.sell_timestamp >= NOW() - INTERVAL '1 hour'
|
||||
GROUP BY s.region_id, s.product_id
|
||||
),
|
||||
world_avg_sales AS (
|
||||
SELECT
|
||||
product_id,
|
||||
AVG(total_sold) AS avg_sold
|
||||
FROM city_sales
|
||||
GROUP BY product_id
|
||||
),
|
||||
parent_region_sales AS (
|
||||
SELECT
|
||||
r.parent_region_id,
|
||||
cs.product_id,
|
||||
AVG(cs.total_sold) AS avg_sold
|
||||
FROM city_sales cs
|
||||
JOIN falukant_data.region r ON r.id = cs.region_id
|
||||
WHERE r.parent_region_id IS NOT NULL
|
||||
GROUP BY r.parent_region_id, cs.product_id
|
||||
),
|
||||
price_updates_world AS (
|
||||
SELECT
|
||||
cs.region_id,
|
||||
cs.product_id,
|
||||
cs.total_sold,
|
||||
COALESCE(wa.avg_sold, 0) AS world_avg,
|
||||
tpw.worth_percent AS current_price,
|
||||
CASE
|
||||
-- Mehr als 5% über dem weltweiten Durchschnitt: 10% teurer
|
||||
WHEN cs.total_sold > COALESCE(wa.avg_sold, 0) * 1.05
|
||||
THEN tpw.worth_percent * 1.1
|
||||
-- Weniger als 5% unter dem weltweiten Durchschnitt: 10% billiger
|
||||
WHEN cs.total_sold < COALESCE(wa.avg_sold, 0) * 0.95
|
||||
THEN tpw.worth_percent * 0.9
|
||||
-- Innerhalb ±5%: Preis bleibt gleich
|
||||
ELSE tpw.worth_percent
|
||||
END AS price_after_world
|
||||
FROM city_sales cs
|
||||
JOIN world_avg_sales wa ON wa.product_id = cs.product_id
|
||||
JOIN falukant_data.town_product_worth tpw
|
||||
ON tpw.region_id = cs.region_id
|
||||
AND tpw.product_id = cs.product_id
|
||||
-- Nur updaten wenn es eine Änderung gibt (außerhalb der ±5% Toleranz)
|
||||
WHERE cs.total_sold > COALESCE(wa.avg_sold, 0) * 1.05
|
||||
OR cs.total_sold < COALESCE(wa.avg_sold, 0) * 0.95
|
||||
),
|
||||
all_cities_with_prices AS (
|
||||
SELECT
|
||||
cs.region_id,
|
||||
cs.product_id,
|
||||
cs.total_sold,
|
||||
r.parent_region_id,
|
||||
tpw.worth_percent AS original_price,
|
||||
COALESCE(puw.price_after_world, tpw.worth_percent) AS price_after_world
|
||||
FROM city_sales cs
|
||||
JOIN falukant_data.region r ON r.id = cs.region_id
|
||||
JOIN falukant_data.town_product_worth tpw
|
||||
ON tpw.region_id = cs.region_id
|
||||
AND tpw.product_id = cs.product_id
|
||||
LEFT JOIN price_updates_world puw
|
||||
ON puw.region_id = cs.region_id
|
||||
AND puw.product_id = cs.product_id
|
||||
),
|
||||
price_updates_parent AS (
|
||||
SELECT
|
||||
acwp.region_id,
|
||||
acwp.product_id,
|
||||
acwp.total_sold,
|
||||
acwp.parent_region_id,
|
||||
COALESCE(prs.avg_sold, 0) AS parent_avg,
|
||||
acwp.price_after_world AS current_price,
|
||||
CASE
|
||||
-- Mehr als 5% über dem parent-region Durchschnitt: 5% teurer
|
||||
WHEN acwp.total_sold > COALESCE(prs.avg_sold, 0) * 1.05
|
||||
THEN acwp.price_after_world * 1.05
|
||||
-- Weniger als 5% unter dem parent-region Durchschnitt: 5% billiger
|
||||
WHEN acwp.total_sold < COALESCE(prs.avg_sold, 0) * 0.95
|
||||
THEN acwp.price_after_world * 0.95
|
||||
-- Innerhalb ±5%: Preis bleibt gleich (vom world-update)
|
||||
ELSE acwp.price_after_world
|
||||
END AS new_price
|
||||
FROM all_cities_with_prices acwp
|
||||
LEFT JOIN parent_region_sales prs
|
||||
ON prs.parent_region_id = acwp.parent_region_id
|
||||
AND prs.product_id = acwp.product_id
|
||||
WHERE acwp.parent_region_id IS NOT NULL
|
||||
AND (
|
||||
acwp.total_sold > COALESCE(prs.avg_sold, 0) * 1.05
|
||||
OR acwp.total_sold < COALESCE(prs.avg_sold, 0) * 0.95
|
||||
)
|
||||
),
|
||||
final_price_updates AS (
|
||||
SELECT
|
||||
COALESCE(pup.region_id, puw.region_id) AS region_id,
|
||||
COALESCE(pup.product_id, puw.product_id) AS product_id,
|
||||
COALESCE(pup.new_price, puw.price_after_world, acwp.original_price) AS final_price
|
||||
FROM all_cities_with_prices acwp
|
||||
LEFT JOIN price_updates_world puw
|
||||
ON puw.region_id = acwp.region_id
|
||||
AND puw.product_id = acwp.product_id
|
||||
LEFT JOIN price_updates_parent pup
|
||||
ON pup.region_id = acwp.region_id
|
||||
AND pup.product_id = acwp.product_id
|
||||
WHERE puw.region_id IS NOT NULL
|
||||
OR pup.region_id IS NOT NULL
|
||||
)
|
||||
UPDATE falukant_data.town_product_worth tpw
|
||||
SET worth_percent = GREATEST(
|
||||
0,
|
||||
LEAST(
|
||||
100,
|
||||
fpu.final_price
|
||||
)
|
||||
)
|
||||
FROM final_price_updates fpu
|
||||
WHERE tpw.region_id = fpu.region_id
|
||||
AND tpw.product_id = fpu.product_id;
|
||||
"#;
|
||||
|
||||
// Ehen / Beziehungen
|
||||
const QUERY_SET_MARRIAGES_BY_PARTY: &str = r#"
|
||||
WITH updated_relations AS (
|
||||
UPDATE falukant_data.relationship AS rel
|
||||
SET relationship_type_id = (
|
||||
SELECT id
|
||||
FROM falukant_type.relationship AS rt
|
||||
WHERE rt.tr = 'married'
|
||||
)
|
||||
WHERE rel.id IN (
|
||||
SELECT rel2.id
|
||||
FROM falukant_data.party AS p
|
||||
JOIN falukant_type.party AS pt
|
||||
ON pt.id = p.party_type_id
|
||||
AND pt.tr = 'wedding'
|
||||
JOIN falukant_data.falukant_user AS fu
|
||||
ON fu.id = p.falukant_user_id
|
||||
JOIN falukant_data.character AS c
|
||||
ON c.user_id = fu.id
|
||||
JOIN falukant_data.relationship AS rel2
|
||||
ON rel2.character1_id = c.id
|
||||
OR rel2.character2_id = c.id
|
||||
JOIN falukant_type.relationship AS rt2
|
||||
ON rt2.id = rel2.relationship_type_id
|
||||
AND rt2.tr = 'engaged'
|
||||
WHERE p.created_at <= NOW() - INTERVAL '1 day'
|
||||
)
|
||||
RETURNING character1_id, character2_id
|
||||
)
|
||||
SELECT
|
||||
c1.user_id AS character1_user,
|
||||
c2.user_id AS character2_user
|
||||
FROM updated_relations AS ur
|
||||
JOIN falukant_data.character AS c1
|
||||
ON c1.id = ur.character1_id
|
||||
JOIN falukant_data.character AS c2
|
||||
ON c2.id = ur.character2_id;
|
||||
"#;
|
||||
|
||||
// Lernen / Studium
|
||||
const QUERY_GET_STUDYINGS_TO_EXECUTE: &str = r#"
|
||||
SELECT
|
||||
l.id,
|
||||
l.associated_falukant_user_id,
|
||||
l.associated_learning_character_id,
|
||||
l.learn_all_products,
|
||||
l.learning_recipient_id,
|
||||
l.product_id,
|
||||
lr.tr
|
||||
FROM falukant_data.learning l
|
||||
JOIN falukant_type.learn_recipient lr
|
||||
ON lr.id = l.learning_recipient_id
|
||||
WHERE l.learning_is_executed = FALSE
|
||||
AND l.created_at + INTERVAL '1 day' < NOW();
|
||||
"#;
|
||||
|
||||
const QUERY_GET_OWN_CHARACTER_ID: &str = r#"
|
||||
SELECT id
|
||||
FROM falukant_data.character c
|
||||
WHERE c.user_id = $1;
|
||||
"#;
|
||||
|
||||
const QUERY_INCREASE_ONE_PRODUCT_KNOWLEDGE: &str = r#"
|
||||
UPDATE falukant_data.knowledge k
|
||||
SET knowledge = LEAST(100, k.knowledge + $1)
|
||||
WHERE k.character_id = $2
|
||||
AND k.product_id = $3;
|
||||
"#;
|
||||
|
||||
const QUERY_INCREASE_ALL_PRODUCTS_KNOWLEDGE: &str = r#"
|
||||
UPDATE falukant_data.knowledge k
|
||||
SET knowledge = LEAST(100, k.knowledge + $1)
|
||||
WHERE k.character_id = $2;
|
||||
"#;
|
||||
|
||||
const QUERY_SET_LEARNING_DONE: &str = r#"
|
||||
UPDATE falukant_data.learning
|
||||
SET learning_is_executed = TRUE
|
||||
WHERE id = $1;
|
||||
"#;
|
||||
|
||||
impl ValueRecalculationWorker {
|
||||
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
|
||||
@@ -601,7 +337,7 @@ impl ValueRecalculationWorker {
|
||||
let rows = conn.execute("get_own_character_id", &[&falukant_user_id])?;
|
||||
|
||||
Ok(rows
|
||||
.get(0)
|
||||
.first()
|
||||
.and_then(|r| r.get("id"))
|
||||
.and_then(|v| v.parse::<i32>().ok()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user