2019-12-03 12:42:43 +01:00
|
|
|
import 'dart:math';
|
|
|
|
|
|
2020-04-12 19:21:53 +02:00
|
|
|
import 'package:moor/moor.dart';
|
2019-12-03 12:03:39 +01:00
|
|
|
|
2020-04-25 17:30:37 +02:00
|
|
|
import 'info.dart';
|
|
|
|
|
|
2019-12-03 12:03:39 +01:00
|
|
|
part 'database.g.dart';
|
|
|
|
|
|
2019-12-03 12:42:43 +01:00
|
|
|
final _random = Random(DateTime.now().millisecondsSinceEpoch);
|
|
|
|
|
int generateId() => _random.nextInt(0xFFFFFFFF);
|
|
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
class WorkPartData {
|
2020-03-21 14:34:45 +01:00
|
|
|
final Work work;
|
|
|
|
|
final List<int> instrumentIds;
|
|
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
WorkPartData({
|
|
|
|
|
this.work,
|
|
|
|
|
this.instrumentIds,
|
2020-03-21 14:34:45 +01:00
|
|
|
});
|
2020-04-25 10:36:19 +02:00
|
|
|
|
|
|
|
|
factory WorkPartData.fromJson(Map<String, dynamic> json) => WorkPartData(
|
|
|
|
|
work: Work.fromJson(json['work']),
|
|
|
|
|
instrumentIds: List<int>.from(json['instrumentIds']),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
|
|
|
'work': work.toJson(),
|
|
|
|
|
'instrumentIds': instrumentIds,
|
|
|
|
|
};
|
2020-03-21 14:34:45 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
class WorkData {
|
|
|
|
|
final WorkPartData data;
|
|
|
|
|
final List<WorkPartData> partData;
|
2020-03-22 16:46:28 +01:00
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
WorkData({
|
|
|
|
|
this.data,
|
|
|
|
|
this.partData,
|
2020-03-22 16:46:28 +01:00
|
|
|
});
|
2020-04-25 10:36:19 +02:00
|
|
|
|
|
|
|
|
factory WorkData.fromJson(Map<String, dynamic> json) => WorkData(
|
|
|
|
|
data: WorkPartData.fromJson(json['data']),
|
|
|
|
|
partData: json['partData']
|
|
|
|
|
.map<WorkPartData>((j) => WorkPartData.fromJson(j))
|
|
|
|
|
.toList(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
|
|
|
'data': data.toJson(),
|
|
|
|
|
'partData': partData.map((d) => d.toJson()).toList(),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RecordingData {
|
|
|
|
|
final Recording recording;
|
|
|
|
|
final List<Performance> performances;
|
|
|
|
|
|
|
|
|
|
RecordingData({
|
|
|
|
|
this.recording,
|
|
|
|
|
this.performances,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
factory RecordingData.fromJson(Map<String, dynamic> json) => RecordingData(
|
|
|
|
|
recording: Recording.fromJson(json['recording']),
|
|
|
|
|
performances: json['performances']
|
|
|
|
|
.map<Performance>((j) => Performance.fromJson(j))
|
|
|
|
|
.toList(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
|
|
|
'recording': recording.toJson(),
|
|
|
|
|
'performances': performances.map((p) => p.toJson()).toList(),
|
|
|
|
|
};
|
2020-03-22 16:46:28 +01:00
|
|
|
}
|
|
|
|
|
|
2019-12-03 12:03:39 +01:00
|
|
|
@UseMoor(
|
|
|
|
|
include: {
|
|
|
|
|
'database.moor',
|
|
|
|
|
},
|
|
|
|
|
)
|
2020-04-24 22:55:45 +02:00
|
|
|
class Database extends _$Database {
|
|
|
|
|
Database(QueryExecutor queryExecutor) : super(queryExecutor);
|
|
|
|
|
|
2020-04-17 17:25:25 +02:00
|
|
|
Database.connect(DatabaseConnection connection) : super.connect(connection);
|
2019-12-03 12:03:39 +01:00
|
|
|
|
|
|
|
|
@override
|
2019-12-04 20:48:03 +01:00
|
|
|
int get schemaVersion => 1;
|
2019-12-03 12:03:39 +01:00
|
|
|
|
2020-03-21 15:41:03 +01:00
|
|
|
@override
|
2020-03-31 15:49:15 +02:00
|
|
|
MigrationStrategy get migration => MigrationStrategy(
|
|
|
|
|
beforeOpen: (details) async {
|
|
|
|
|
await customStatement('PRAGMA foreign_keys = ON');
|
|
|
|
|
},
|
|
|
|
|
);
|
2020-03-21 15:41:03 +01:00
|
|
|
|
2019-12-03 12:03:39 +01:00
|
|
|
Future<void> updatePerson(Person person) async {
|
2020-03-21 15:08:50 +01:00
|
|
|
await into(persons).insert(person, orReplace: true);
|
2019-12-03 12:03:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> updateInstrument(Instrument instrument) async {
|
2020-03-21 15:08:50 +01:00
|
|
|
await into(instruments).insert(instrument, orReplace: true);
|
2019-12-03 12:03:39 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-25 17:30:37 +02:00
|
|
|
/// Retrieve more information on an already queried work.
|
|
|
|
|
Future<WorkInfo> getWorkInfo(Work work) async {
|
|
|
|
|
final id = work.id;
|
|
|
|
|
|
|
|
|
|
final composers = await composersByWork(id).get();
|
|
|
|
|
final instruments = await instrumentsByWork(id).get();
|
|
|
|
|
|
|
|
|
|
final List<PartInfo> parts = [];
|
|
|
|
|
for (final part in await workParts(id).get()) {
|
|
|
|
|
parts.add(PartInfo(
|
|
|
|
|
work: part,
|
|
|
|
|
composer: part.composer != null
|
|
|
|
|
? await personById(part.composer).getSingle()
|
|
|
|
|
: null,
|
|
|
|
|
instruments: await instrumentsByWork(id).get(),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return WorkInfo(
|
|
|
|
|
work: work,
|
|
|
|
|
instruments: instruments,
|
|
|
|
|
composers: composers,
|
|
|
|
|
parts: parts,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get all available information on a work.
|
|
|
|
|
Future<WorkInfo> getWork(int id) async {
|
|
|
|
|
final work = await workById(id).getSingle();
|
|
|
|
|
return await getWorkInfo(work);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get information on all works written by the person with ID [personId].
|
|
|
|
|
Future<List<WorkInfo>> getWorks(int personId) async {
|
|
|
|
|
final works = await worksByComposer(personId).get();
|
|
|
|
|
|
|
|
|
|
final List<WorkInfo> result = [];
|
|
|
|
|
for (final work in works) {
|
|
|
|
|
result.add(await getWorkInfo(work));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
Future<void> updateWork(WorkData data) async {
|
2019-12-03 12:03:39 +01:00
|
|
|
await transaction(() async {
|
2020-04-25 10:36:19 +02:00
|
|
|
final workId = data.data.work.id;
|
2020-03-21 14:34:45 +01:00
|
|
|
await (delete(works)..where((w) => w.id.equals(workId))).go();
|
|
|
|
|
await (delete(works)..where((w) => w.partOf.equals(workId))).go();
|
2019-12-03 12:03:39 +01:00
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
Future<void> insertWork(WorkPartData partData) async {
|
|
|
|
|
await into(works).insert(partData.work);
|
2020-03-21 14:34:45 +01:00
|
|
|
await batch((b) => b.insertAll(
|
|
|
|
|
instrumentations,
|
2020-04-25 10:36:19 +02:00
|
|
|
partData.instrumentIds
|
2020-03-21 14:34:45 +01:00
|
|
|
.map((id) =>
|
2020-04-25 10:36:19 +02:00
|
|
|
Instrumentation(work: partData.work.id, instrument: id))
|
2020-03-21 14:34:45 +01:00
|
|
|
.toList()));
|
|
|
|
|
}
|
2019-12-03 12:03:39 +01:00
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
await insertWork(data.data);
|
|
|
|
|
for (final partData in data.partData) {
|
|
|
|
|
await insertWork(partData);
|
2020-03-21 14:34:45 +01:00
|
|
|
}
|
2019-12-03 12:03:39 +01:00
|
|
|
});
|
|
|
|
|
}
|
2020-03-22 14:49:40 +01:00
|
|
|
|
|
|
|
|
Future<void> updateEnsemble(Ensemble ensemble) async {
|
|
|
|
|
await into(ensembles).insert(ensemble, orReplace: true);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 10:36:19 +02:00
|
|
|
Future<void> updateRecording(RecordingData data) async {
|
2020-03-22 14:49:40 +01:00
|
|
|
await transaction(() async {
|
2020-03-22 16:31:38 +01:00
|
|
|
await (delete(performances)
|
2020-04-25 10:36:19 +02:00
|
|
|
..where((p) => p.recording.equals(data.recording.id)))
|
2020-03-22 16:31:38 +01:00
|
|
|
.go();
|
2020-04-25 10:36:19 +02:00
|
|
|
await into(recordings).insert(data.recording, orReplace: true);
|
|
|
|
|
for (final performance in data.performances) {
|
|
|
|
|
await into(performances).insert(performance);
|
2020-03-22 14:49:40 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-04-25 17:30:37 +02:00
|
|
|
|
|
|
|
|
/// Retreive more information on an already queried recording.
|
|
|
|
|
Future<RecordingInfo> getRecordingInfo(Recording recording) async {
|
|
|
|
|
final id = recording.id;
|
|
|
|
|
|
|
|
|
|
final List<PerformanceInfo> performances = [];
|
|
|
|
|
for (final performance in await performancesByRecording(id).get()) {
|
|
|
|
|
performances.add(PerformanceInfo(
|
|
|
|
|
person: performance.person != null
|
|
|
|
|
? await personById(performance.person).getSingle()
|
|
|
|
|
: null,
|
|
|
|
|
ensemble: performance.ensemble != null
|
|
|
|
|
? await ensembleById(performance.ensemble).getSingle()
|
|
|
|
|
: null,
|
|
|
|
|
role: performance.role != null
|
|
|
|
|
? await instrumentById(performance.role).getSingle()
|
|
|
|
|
: null,
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RecordingInfo(
|
|
|
|
|
recording: recording,
|
|
|
|
|
performances: performances,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get all available information on a recording.
|
|
|
|
|
Future<RecordingInfo> getRecording(int id) async {
|
|
|
|
|
final recording = await recordingById(id).getSingle();
|
|
|
|
|
return await getRecordingInfo(recording);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get information on all recordings of the work with ID [workId].
|
|
|
|
|
Future<List<RecordingInfo>> getRecordings(int workId) async {
|
|
|
|
|
final recordings = await recordingsByWork(workId).get();
|
|
|
|
|
|
|
|
|
|
final List<RecordingInfo> result = [];
|
|
|
|
|
for (final recording in recordings) {
|
|
|
|
|
result.add(await getRecordingInfo(recording));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-12-03 12:03:39 +01:00
|
|
|
}
|