175 lines
5.0 KiB
Dart
175 lines
5.0 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:latlong2/latlong.dart';
|
||
|
||
enum PlaceTrait {
|
||
calm,
|
||
alive,
|
||
cozy,
|
||
cold,
|
||
status,
|
||
simple,
|
||
free,
|
||
formal,
|
||
private,
|
||
open,
|
||
social,
|
||
solo,
|
||
beautiful,
|
||
neutral,
|
||
unusual,
|
||
clear,
|
||
focused,
|
||
transit,
|
||
}
|
||
|
||
extension PlaceTraitText on PlaceTrait {
|
||
String get label {
|
||
return switch (this) {
|
||
PlaceTrait.calm => 'спокойное',
|
||
PlaceTrait.alive => 'живое',
|
||
PlaceTrait.cozy => 'уютное',
|
||
PlaceTrait.cold => 'холодное',
|
||
PlaceTrait.status => 'статусное',
|
||
PlaceTrait.simple => 'простое',
|
||
PlaceTrait.free => 'свободное',
|
||
PlaceTrait.formal => 'формальное',
|
||
PlaceTrait.private => 'приватное',
|
||
PlaceTrait.open => 'открытое',
|
||
PlaceTrait.social => 'для общения',
|
||
PlaceTrait.solo => 'для себя',
|
||
PlaceTrait.beautiful => 'красивое',
|
||
PlaceTrait.neutral => 'нейтральное',
|
||
PlaceTrait.unusual => 'необычное',
|
||
PlaceTrait.clear => 'понятное',
|
||
PlaceTrait.focused => 'помогает собраться',
|
||
PlaceTrait.transit => 'транзитное',
|
||
};
|
||
}
|
||
}
|
||
|
||
enum UserIntent { exhale, date, meet, focus, move, surprise, alone, impress }
|
||
|
||
extension UserIntentText on UserIntent {
|
||
String get title {
|
||
return switch (this) {
|
||
UserIntent.exhale => 'выдохнуть',
|
||
UserIntent.date => 'свидание',
|
||
UserIntent.meet => 'встретиться',
|
||
UserIntent.focus => 'поработать',
|
||
UserIntent.move => 'движ',
|
||
UserIntent.surprise => 'удивиться',
|
||
UserIntent.alone => 'побыть одному',
|
||
UserIntent.impress => 'привести кого-то',
|
||
};
|
||
}
|
||
|
||
String get subtitle {
|
||
return switch (this) {
|
||
UserIntent.exhale => 'тихо, мягко, без давления',
|
||
UserIntent.date => 'красиво и лично',
|
||
UserIntent.meet => 'общение без лишней формальности',
|
||
UserIntent.focus => 'собраться и не выпадать',
|
||
UserIntent.move => 'живо, шумно, с энергией',
|
||
UserIntent.surprise => 'не как обычно',
|
||
UserIntent.alone => 'быть в своем ритме',
|
||
UserIntent.impress => 'место должно держать момент',
|
||
};
|
||
}
|
||
|
||
IconData get icon {
|
||
return switch (this) {
|
||
UserIntent.exhale => Icons.air_outlined,
|
||
UserIntent.date => Icons.favorite_border,
|
||
UserIntent.meet => Icons.forum_outlined,
|
||
UserIntent.focus => Icons.center_focus_strong_outlined,
|
||
UserIntent.move => Icons.bolt_outlined,
|
||
UserIntent.surprise => Icons.auto_awesome_outlined,
|
||
UserIntent.alone => Icons.person_outline,
|
||
UserIntent.impress => Icons.diamond_outlined,
|
||
};
|
||
}
|
||
|
||
Set<PlaceTrait> get traits {
|
||
return switch (this) {
|
||
UserIntent.exhale => {PlaceTrait.calm, PlaceTrait.cozy, PlaceTrait.solo},
|
||
UserIntent.date => {
|
||
PlaceTrait.private,
|
||
PlaceTrait.beautiful,
|
||
PlaceTrait.social,
|
||
},
|
||
UserIntent.meet => {PlaceTrait.social, PlaceTrait.free, PlaceTrait.alive},
|
||
UserIntent.focus => {
|
||
PlaceTrait.focused,
|
||
PlaceTrait.calm,
|
||
PlaceTrait.neutral,
|
||
},
|
||
UserIntent.move => {PlaceTrait.alive, PlaceTrait.open, PlaceTrait.social},
|
||
UserIntent.surprise => {
|
||
PlaceTrait.unusual,
|
||
PlaceTrait.alive,
|
||
PlaceTrait.open,
|
||
},
|
||
UserIntent.alone => {PlaceTrait.solo, PlaceTrait.free, PlaceTrait.calm},
|
||
UserIntent.impress => {
|
||
PlaceTrait.status,
|
||
PlaceTrait.beautiful,
|
||
PlaceTrait.private,
|
||
},
|
||
};
|
||
}
|
||
}
|
||
|
||
class PlaceRecommendation {
|
||
const PlaceRecommendation({
|
||
required this.id,
|
||
required this.name,
|
||
required this.area,
|
||
required this.photoUrls,
|
||
required this.coordinate,
|
||
required this.traits,
|
||
});
|
||
|
||
final String id;
|
||
final String name;
|
||
final String area;
|
||
final List<String> photoUrls;
|
||
final LatLng coordinate;
|
||
final Set<PlaceTrait> traits;
|
||
|
||
String get coverPhotoUrl => photoUrls.first;
|
||
}
|
||
|
||
class VoiceReviewDraft {
|
||
const VoiceReviewDraft({
|
||
required this.placeName,
|
||
required this.duration,
|
||
required this.extractedTraits,
|
||
required this.suggestedIntents,
|
||
required this.evidence,
|
||
});
|
||
|
||
final String placeName;
|
||
final Duration duration;
|
||
final Set<PlaceTrait> extractedTraits;
|
||
final Set<UserIntent> suggestedIntents;
|
||
final List<String> evidence;
|
||
|
||
bool get isLongEnough => duration.inSeconds >= 30;
|
||
|
||
VoiceReviewDraft copyWith({
|
||
String? placeName,
|
||
Duration? duration,
|
||
Set<PlaceTrait>? extractedTraits,
|
||
Set<UserIntent>? suggestedIntents,
|
||
List<String>? evidence,
|
||
}) {
|
||
return VoiceReviewDraft(
|
||
placeName: placeName ?? this.placeName,
|
||
duration: duration ?? this.duration,
|
||
extractedTraits: extractedTraits ?? this.extractedTraits,
|
||
suggestedIntents: suggestedIntents ?? this.suggestedIntents,
|
||
evidence: evidence ?? this.evidence,
|
||
);
|
||
}
|
||
}
|