упр.05 задача 2
- Краен срок:
- 12.11.2025 23:59
- Точки:
- 3
Срокът за предаване на решения е отминал
Напишете програма за работа с данни от сензори на произволен компютър.
Имате следните структури (може да добавяте допълнителни derive-ове и trait имплементации, ако ви трябват).
struct Event {
timestamp: u64,
sensor: String,
metric: SensorMetric,
value: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum SensorMetric {
Load,
Frequency,
Temperature,
}
Имплементирайте следната много генерална помощна функция, която:
- приема списък от събития
- групира събитията по ключ
K - взима данните за агрегация
D, от всяко събитие, ако има такива - за всеки различен ключ
K, прилага функциятаaggregateвърху всички данни, отговарящи на този ключ и записва в hash map ключа и резултата от агрегацията
(Можем ли да го направим по-лесно или по-ефективно с итератори? Сигурно. Но пробвайте така).
fn group_and_aggregate<O, E, D, K>(
events: &[E],
group_fn: impl Fn(&E) -> K,
data_fn: impl Fn(&E) -> Option<D>,
aggregate: impl Fn(&[D]) -> O,
) -> HashMap<K, O>
where
K: Eq + Hash,
{
todo!()
}
Имплементирайте следните две агрегации, които могат да се приложат върху списък от данни, върнати от сензорите.
Използвайте помощната функция, дефинирана по-горе, доколкото можете.
Можете и да използвате всякакви други функционалности от стандартната библиотека.
trait Aggregator {
type Output;
fn name(&self) -> String;
fn aggregate(&self, events: &[Event]) -> Vec<(String, Self::Output)>;
}
// Имплементирайте агрегация, която връща средната стойност на метриките, групирани по тип.
// Резултата трябва да е вектор от три елемента:
// - ("Load", <средната стойност на Load метриките от всички сензори>)
// - ("Frequency", <средната стойност на Frequency метриките от всички сензори>)
// - ("Temperature", <средната стойност на Temperature метриките от всички сензори>)
struct TotalAggregator {}
impl Aggregator for TotalAggregator {
type Output = f64;
fn name(&self) -> String {
"total".to_string()
}
fn aggregate(&self, events: &[Event]) -> Vec<(String, f64)> {
todo!()
}
}
// Имплементирайте агрегация, която по даден тип на метрика, връща сумата от метриките
// от този тип, групирани по сензор.
// Пример при `MetricAggreator { metric: SensorMetric::Load }`, може да върне:
// - ("cpu0", <средната стойност от Load метиките за сензор cpu0>)
// - ("cpu1", <средната стойност от Load метиките за сензор cpu1>)
// - ("gpu0", <средната стойност от Load метиките за сензор gpu0>)
struct MetricAggregator {
metric: SensorMetric
}
impl Aggregator for MetricAggregator {
type Output = f64;
fn name(&self) -> String {
format!("{:?}", self.metric);
}
fn aggregate(&self, events: &[Event]) -> Vec<(String, f64)> {
todo!();
}
}
Пример за изпозлване
fn main() {
let all: Vec<Box<dyn Aggregator<Output=f64>>> = vec![
Box::new(TotalAggregator{}),
Box::new(MetricAggregator{metric: SensorMetric::Load}),
Box::new(MetricAggregator{metric: SensorMetric::Temperature}),
];
let events = &[
Event { timestamp: 0, sensor: String::from("cpu0"), metric: SensorMetric::Load, value: 0.98 },
Event { timestamp: 0, sensor: String::from("cpu1"), metric: SensorMetric::Load, value: 0.04 },
Event { timestamp: 0, sensor: String::from("gpu0"), metric: SensorMetric::Load, value: 13.45 },
Event { timestamp: 0, sensor: String::from("cpu0"), metric: SensorMetric::Frequency, value: 3100.00 },
Event { timestamp: 0, sensor: String::from("cpu1"), metric: SensorMetric::Frequency, value: 3100.00 },
Event { timestamp: 0, sensor: String::from("gpu0"), metric: SensorMetric::Frequency, value: 300.00 },
Event { timestamp: 0, sensor: String::from("cpu0"), metric: SensorMetric::Temperature, value: 56.20 },
Event { timestamp: 0, sensor: String::from("cpu1"), metric: SensorMetric::Temperature, value: 33.33 },
Event { timestamp: 0, sensor: String::from("gpu0"), metric: SensorMetric::Temperature, value: 25.00 },
];
for aggr in &all {
for (key, val) in aggr.aggregate(events) {
println!("{} {:?}: {:.02}", aggr.name(), key, val);
}
}
// total "Temperature": 38.18
// total "Load": 4.82
// total "Frequency": 2166.67
// Load "gpu0": 13.45
// Load "cpu1": 0.04
// Load "cpu0": 0.98
// Temperature "cpu1": 33.33
// Temperature "cpu0": 56.20
// Temperature "gpu0": 25.00
}
Задължително прочетете (или си припомнете): Указания за предаване на домашни
Погрижете се решението ви да се компилира с базовия тест:
