ponshu-room-lite/lib/models/sakenowa/sakenowa_models.dart

195 lines
4.9 KiB
Dart
Raw Normal View History

// さけのわAPI データモデル
// API Documentation: https://muro.sakenowa.com/sakenowa-data/api/
/// 銘柄データ
class SakenowaBrand {
final int id;
final String name;
final int breweryId;
const SakenowaBrand({
required this.id,
required this.name,
required this.breweryId,
});
factory SakenowaBrand.fromJson(Map<String, dynamic> json) {
return SakenowaBrand(
id: json['id'] as int,
name: json['name'] as String,
breweryId: json['breweryId'] as int,
);
}
}
/// 蔵元データ
class SakenowaBrewery {
final int id;
final String name;
final int areaId;
const SakenowaBrewery({
required this.id,
required this.name,
required this.areaId,
});
factory SakenowaBrewery.fromJson(Map<String, dynamic> json) {
return SakenowaBrewery(
id: json['id'] as int,
name: json['name'] as String,
areaId: json['areaId'] as int,
);
}
}
/// 地域データ
class SakenowaArea {
final int id;
final String name;
const SakenowaArea({
required this.id,
required this.name,
});
factory SakenowaArea.fromJson(Map<String, dynamic> json) {
return SakenowaArea(
id: json['id'] as int,
name: json['name'] as String,
);
}
}
/// 6軸フレーバーチャート
/// f1: 華やか, f2: 芳醇, f3: 重厚, f4: 穏やか, f5: 軽快, f6: ドライ
class SakenowaFlavorChart {
final int brandId;
final double f1; // 華やか
final double f2; // 芳醇
final double f3; // 重厚
final double f4; // 穏やか
final double f5; // 軽快
final double f6; // ドライ
const SakenowaFlavorChart({
required this.brandId,
required this.f1,
required this.f2,
required this.f3,
required this.f4,
required this.f5,
required this.f6,
});
factory SakenowaFlavorChart.fromJson(Map<String, dynamic> json) {
return SakenowaFlavorChart(
brandId: json['brandId'] as int,
f1: (json['f1'] as num).toDouble(),
f2: (json['f2'] as num).toDouble(),
f3: (json['f3'] as num).toDouble(),
f4: (json['f4'] as num).toDouble(),
f5: (json['f5'] as num).toDouble(),
f6: (json['f6'] as num).toDouble(),
);
}
/// 軸名のラベル
static const axisLabels = {
'f1': '華やか',
'f2': '芳醇',
'f3': '重厚',
'f4': '穏やか',
'f5': '軽快',
'f6': 'ドライ',
};
/// レーダーチャート用のリストに変換
List<double> toList() => [f1, f2, f3, f4, f5, f6];
/// 五味チャート形式に変換(互換性維持)
/// 既存の五味チャートaroma, sweetness, acidity, bitterness, bodyに対応
Map<String, double> toFiveAxisTaste() {
return {
'aroma': f1, // 華やか → 香り
'sweetness': (f2 + f4) / 2, // 芳醇・穏やか → 甘み
'acidity': f5, // 軽快 → 酸味
'bitterness': f6, // ドライ → キレ
'body': f3, // 重厚 → コク
};
}
/// 五味チャート形式1-5スケールに変換
/// Gemini AI解析結果との互換性維持
Map<String, int> toFiveAxisTasteInt() {
final fiveAxis = toFiveAxisTaste();
return fiveAxis.map((k, v) => MapEntry(k, (v * 5).round().clamp(1, 5)));
}
/// レーダーチャート表示用6軸、ラベル付き
List<MapEntry<String, double>> toRadarData() {
return [
MapEntry(axisLabels['f1']!, f1),
MapEntry(axisLabels['f2']!, f2),
MapEntry(axisLabels['f3']!, f3),
MapEntry(axisLabels['f4']!, f4),
MapEntry(axisLabels['f5']!, f5),
MapEntry(axisLabels['f6']!, f6),
];
}
/// 英語ラベルでのレーダーチャート用
List<MapEntry<String, double>> toRadarDataEn() {
return [
MapEntry('Elegant', f1), // 華やか
MapEntry('Rich', f2), // 芳醇
MapEntry('Full', f3), // 重厚
MapEntry('Mild', f4), // 穏やか
MapEntry('Light', f5), // 軽快
MapEntry('Dry', f6), // ドライ
];
}
}
/// ランキングエントリ
class SakenowaRanking {
final int rank;
final int brandId;
final int? areaId;
final double score;
const SakenowaRanking({
required this.rank,
required this.brandId,
this.areaId,
required this.score,
});
factory SakenowaRanking.fromJson(Map<String, dynamic> json) {
return SakenowaRanking(
rank: json['rank'] as int,
brandId: json['brandId'] as int,
areaId: json['areaId'] as int?,
score: (json['score'] as num).toDouble(),
);
}
}
/// フレーバータグ
class SakenowaFlavorTag {
final int id;
final String tag;
const SakenowaFlavorTag({
required this.id,
required this.tag,
});
factory SakenowaFlavorTag.fromJson(Map<String, dynamic> json) {
return SakenowaFlavorTag(
id: json['id'] as int,
tag: json['tag'] as String,
);
}
}