編集: 2013 年 9 月 15 日 - 私の状況をよりよく理解できるように、私のシナリオをさらにいくつかのステップに分けて説明しています。ダウンロード用のアプリケーション全体のソースも追加しました。元の質問にジャンプする場合は、最後の見出しまでスクロールします。質問を教えてください。ありがとう
概要
アラスカ州の州都ジュノーには AST (アラスカ州警察) の本部ビルがあり、1 つの番号が自動的に表示および更新される大きな画面を表示したいと考えています。その数は(Crime Quotient Index)またはCQIと呼ばれます
CQI は基本的に、現在の州の犯罪状況を示すために計算された数値です...
どのように計算されますか?
画面を実行するプログラムは、Hot IObservable ストリームを通じて CrimeReport オブジェクトを常に受信する .NET WPF アプリケーションです。
CQI は都市ごとに計算され、州 CQI と呼ばれるすべての都市の Sum() が取得されます。州 CQI を計算する手順は次のとおりです。
ステップ 1 - 犯罪データを受け取る
CrimeReport は、犯罪が報告されるたびに .NET アプリケーションに送信されます。次のコンポーネントがあります。
犯行日時
市- 管轄の市/郡
SeverityLevel - 重大/非重大
EstimatedSolveTime - 犯罪の解決にかかると AST が判断した推定日数。
したがって、このステップでは、IObservable をサブスクライブし、MainViewModel のインスタンスを作成します。
IObservable<CrimeReport> reportSource = mainSource.Publish();
MainVM = new MainViewModel(reportSource);
reportSource.Connect();
ステップ 2 - 都市ごとにグループ化し、都市ごとに計算する
レポートを受け取ったら、都市ごとにグループ化してください。
var cities = reportSource.GroupBy(k => k.City)
.Select(g => new CityDto(g.Key, g);
CityDto は、現在の都市に関するすべてのレポートを取得し、都市の CQI を計算する DTO クラスです。
City の CQI の計算は、次の式で行われます。
重大でない犯罪の総数に対する重大な犯罪の総数の比率が 1 未満の場合
それから
都市の CQI = 比率 x 推定解決時間の最小値
そうしないと
都市の CQI = 比率 x 最大推定解決時間
これは CityDto のクラス定義です
internal class CityDto
{
public string CityName { get; set; }
public IObservable<decimal> CityCqi {get; set;}
public CityDto(string cityName, IObservable<CrimeReport> cityReports)
{
CityName = cityName;
// Get all serious and non serious crimes
//
var totalSeriousCrimes = cityReports.Where(c => c.Severity == CrimeSeverity.Serious)
.Scan(0, (p, _) => p++);
var totalnonSeriousCrimes = cityReports.Where(c => c.Severity == CrimeSeverity.NonSerious)
.Scan(0, (p, _) => p++);
// Get the ratio
//
var ratio = Observable.CombineLatest(totalSeriousCrimes, totalnonSeriousCrimes,
(s, n) => n == 0? s : s/n); // Avoding DivideByZero here
// Get the minimum and maximum estimated solve time
//
var minEstimatedSolveTime = cityReports.Select(c => c.EstimatedSolveTime)
.Scan(5000, (p, n) => n < p? n : p);
var maxEstimatedSolveTime = cityReports.Select(c=>c.EstimatedSolveTime)
.Scan(0, (p, n) => n > p? n : p);
//Time for the City's CQI
//
CityCqi = Observable.CombineLatest(ratio, minEstimatedSolveTime, maxEstimatedSolveTime, (r, n, x) => r < 1.0? r * n : r * m);
}
}
City の CQI 値を維持し、そのライブ CQI を IObservable を介して公開する City DTO オブジェクトができたので、アラスカ州の州都は、すべての都市の CQI を Sum() してアラスカの CQI として表示し、画面上にライブで表示し、各CQIプログラムに参加している市/郡のどこかで報告された犯罪は、州のCQIに即座に影響を与えるはずです
ステップ 3 - 州の都市のデータをまとめる
ここで、大画面でライブ更新されている州全体の CQI を計算する必要があります。MainViewModel と呼ばれる州のビュー モデルがあります。
internal class MainViewModel
{
public MainViewModel(IObservable<CrimeReport> mainReport)
{
/// Here is the snippet also mentioned in Step 2
//
var cities = mainReport.GroupBy(k => k.City)
.Select(g => new CityDto(g.Key, g));
///// T h i s ///// Is //// Where //// I /// am /// Stuck
//
var allCqis = cities.Select(c => c.CityCqi); // gives you IObservable<IObservable<decimal>> ,
/// Need to use latest of each observable in allCqi and sum them up
//// How do I do it ?
}
}
制約
- 現在、アラスカのすべての都市が州の CQI プログラムに参加しているわけではありませんが、都市は日々登録されているため、リストを取得することはできず、登録に関係なくすべての都市を追加することも現実的ではありません。したがって、参加しているだけでなく、少なくとも 1 つの CrimeReport オブジェクトを送信した都市のみを維持するのは IObservable です。
完全なソース コード
ソースはここをクリックしてダウンロードできます
もともと出題された質問
複数のホット オブザーバブルの 1 つのホット オブザーバブルがあります...
IObservable<IObservable<decimal>>
サブスクライブすると、内部のすべてのオブザーバブルからのすべての「最新」の10進数の合計がオブザーバーに通知されるオブザーバブルが必要です。
どうすればそれを達成できますか? CombineLatest(...) を試しましたが、うまくいきませんでした。
ありがとう