fluffychat/lib/pangea/course_plans/activity_summaries_provider.dart

128 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pangea/bot/utils/bot_name.dart';
import 'package:fluffychat/pangea/chat_settings/utils/room_summary_extension.dart';
import 'package:fluffychat/pangea/course_plans/course_plan_model.dart';
import 'package:fluffychat/pangea/course_plans/course_topic_model.dart';
import 'package:fluffychat/widgets/matrix.dart';
mixin ActivitySummariesProvider<T extends StatefulWidget> on State<T> {
Map<String, RoomSummaryResponse>? roomSummaries;
Future<void> loadRoomSummaries(List<String> roomIds) async {
if (roomIds.isEmpty) {
roomSummaries = {};
return;
}
final resp = await Matrix.of(context).client.requestRoomSummaries(roomIds);
if (mounted) {
setState(() => roomSummaries = resp.summaries);
}
}
Set<String> openSessions(String activityId) {
if (roomSummaries == null || roomSummaries!.isEmpty) return {};
final Set<String> sessions = {};
for (final entry in roomSummaries!.entries) {
final summary = entry.value;
final roomId = entry.key;
if (summary.activityPlan.activityId != activityId) {
continue;
}
final isOpen = summary.activityRoles.roles.length <
summary.activityPlan.req.numberOfParticipants;
if (isOpen) {
sessions.add(roomId);
}
}
return sessions;
}
int numOpenSessions(String activityId) => openSessions(activityId).length;
Set<String> _completedActivities(String userID) {
if (roomSummaries == null || roomSummaries!.isEmpty) return {};
return roomSummaries!.values
.where(
(entry) => entry.activityRoles.roles.values.any(
(v) => v.userId == userID && v.isArchived,
),
)
.map((e) => e.activityPlan.activityId)
.toSet();
}
bool hasCompletedActivity(
String userID,
String activityID,
) {
final completed = _completedActivities(userID);
return completed.contains(activityID);
}
bool _hasCompletedTopic(
String userID,
CourseTopicModel topic,
CoursePlanModel course,
) {
final topicIndex = course.loadedTopics.indexWhere(
(t) => t.uuid == topic.uuid,
);
if (topicIndex == -1) {
throw Exception('Topic not found');
}
final topicActivities = course.loadedTopics[topicIndex].loadedActivities;
final topicActivityIds = topicActivities.map((a) => a.activityId).toSet();
final numTwoPersonActivities =
topicActivities.where((a) => a.req.numberOfParticipants <= 2).length;
final completedTopicActivities =
_completedActivities(userID).intersection(topicActivityIds);
return completedTopicActivities.length >= numTwoPersonActivities;
}
int currentTopicIndex(
String userID,
CoursePlanModel course,
) {
if (course.loadedTopics.isEmpty) return -1;
for (int i = 0; i < course.loadedTopics.length; i++) {
if (!_hasCompletedTopic(userID, course.loadedTopics[i], course)) {
return i;
}
}
return 0;
}
Future<Map<String, List<User>>> topicsToUsers(
Room room,
CoursePlanModel course,
) async {
final Map<String, List<User>> topicUserMap = {};
final users = await room.requestParticipants(
[Membership.join, Membership.invite, Membership.knock],
false,
true,
);
for (final user in users) {
if (user.id == BotName.byEnvironment) continue;
final topicIndex = currentTopicIndex(user.id, course);
if (topicIndex != -1) {
final topicID = course.loadedTopics[topicIndex].uuid;
topicUserMap.putIfAbsent(topicID, () => []).add(user);
}
}
return topicUserMap;
}
}