207 lines
6.2 KiB
Dart
207 lines
6.2 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
|
|
|
import 'performance_test.dart';
|
|
|
|
/// Analyzes various device hardware and software aspects to generate a compatibility score.
|
|
/// This class provides a standardized output for the UI to consume easily.
|
|
class DeviceAnalyzer {
|
|
final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin();
|
|
|
|
/// Reads the total RAM from the system's meminfo file.
|
|
/// Returns the value in Megabytes (MB).
|
|
Future<double> _readTotalRamMB() async {
|
|
try {
|
|
final file = File('/proc/meminfo');
|
|
if (!await file.exists()) return 0.0;
|
|
final lines = await file.readAsLines();
|
|
for (var line in lines) {
|
|
if (line.startsWith('MemTotal')) {
|
|
// Extracts the numeric value from the line.
|
|
final kb = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? '0') ?? 0;
|
|
return kb / 1024.0; // Convert from Kilobytes to Megabytes
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print('❌ Error reading total RAM: $e');
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
/// Reads the current RAM usage percentage from the system's meminfo file.
|
|
Future<double> _readUsedRamPercent() async {
|
|
try {
|
|
final file = File('/proc/meminfo');
|
|
if (!await file.exists()) return 0.0;
|
|
final lines = await file.readAsLines();
|
|
int? total, available;
|
|
for (var line in lines) {
|
|
if (line.startsWith('MemTotal')) {
|
|
total = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? '');
|
|
} else if (line.startsWith('MemAvailable')) {
|
|
available = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? '');
|
|
}
|
|
}
|
|
if (total != null && available != null && total > 0) {
|
|
final used = total - available;
|
|
return (used / total) * 100.0;
|
|
}
|
|
} catch (e) {
|
|
print('❌ Error reading used RAM: $e');
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
/// The main analysis function that runs all checks.
|
|
Future<Map<String, dynamic>> analyzeDevice() async {
|
|
List<Map<String, dynamic>> details = [];
|
|
|
|
if (!Platform.isAndroid) {
|
|
return {
|
|
'score': 0,
|
|
'details': [
|
|
{
|
|
'label': 'النظام غير مدعوم',
|
|
'status': false,
|
|
'achieved_score': 0,
|
|
'max_score': 100
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
final info = await _deviceInfo.androidInfo;
|
|
final data = info.data;
|
|
final features = List<String>.from(data['systemFeatures'] ?? []);
|
|
|
|
// 1. Android Version (Max: 10 points)
|
|
final version =
|
|
int.tryParse(info.version.release?.split('.').first ?? '0') ?? 0;
|
|
final int androidScore = version >= 9 ? 10 : 0;
|
|
details.add({
|
|
'label': 'إصدار أندرويد ${info.version.release}',
|
|
'status': androidScore > 0,
|
|
'achieved_score': androidScore,
|
|
'max_score': 10,
|
|
});
|
|
|
|
// 2. Total RAM (Max: 10 points)
|
|
final totalRam = await _readTotalRamMB();
|
|
int ramScore;
|
|
if (totalRam >= 8000) {
|
|
ramScore = 10;
|
|
} else if (totalRam >= 4000) {
|
|
ramScore = 5;
|
|
} else if (totalRam >= 3000) {
|
|
ramScore = 3;
|
|
} else {
|
|
ramScore = 0;
|
|
}
|
|
details.add({
|
|
'label': 'إجمالي الرام ${totalRam.toStringAsFixed(0)} ميجابايت',
|
|
'status': ramScore >= 5,
|
|
'achieved_score': ramScore,
|
|
'max_score': 10,
|
|
});
|
|
|
|
// 3. CPU Cores (Max: 10 points)
|
|
final cores = Platform.numberOfProcessors;
|
|
int coreScore = cores >= 6 ? 10 : (cores >= 4 ? 5 : 0);
|
|
details.add({
|
|
'label': 'أنوية المعالج ($cores)',
|
|
'status': coreScore >= 5,
|
|
'achieved_score': coreScore,
|
|
'max_score': 10,
|
|
});
|
|
|
|
// 4. Free Storage (Max: 5 points)
|
|
final freeBytes = data['freeDiskSize'] ?? 0;
|
|
final freeGB = freeBytes / (1024 * 1024 * 1024);
|
|
int storeScore = freeGB >= 5 ? 5 : (freeGB >= 2 ? 3 : 0);
|
|
details.add({
|
|
'label': 'المساحة الحرة ${freeGB.toStringAsFixed(1)} جيجابايت',
|
|
'status': storeScore >= 3,
|
|
'achieved_score': storeScore,
|
|
'max_score': 5,
|
|
});
|
|
|
|
// 5. GPS + Gyroscope Sensors (Max: 10 points)
|
|
bool okSensors = features.contains('android.hardware.location.gps') &&
|
|
features.contains('android.hardware.sensor.gyroscope');
|
|
final int sensorScore = okSensors ? 10 : 0;
|
|
details.add({
|
|
'label': 'حساسات GPS و Gyroscope',
|
|
'status': okSensors,
|
|
'achieved_score': sensorScore,
|
|
'max_score': 10,
|
|
});
|
|
|
|
// 6. Storage Write Speed (Max: 20 points)
|
|
final writeSpeed = await PerformanceTester.testStorageWriteSpeed();
|
|
int writeScore;
|
|
if (writeSpeed >= 30) {
|
|
writeScore = 20;
|
|
} else if (writeSpeed >= 15) {
|
|
writeScore = 15;
|
|
} else if (writeSpeed >= 5) {
|
|
writeScore = 10;
|
|
} else {
|
|
writeScore = 5;
|
|
}
|
|
details.add({
|
|
'label': 'سرعة الكتابة (${writeSpeed.toStringAsFixed(1)} MB/s)',
|
|
'status': writeScore >= 10,
|
|
'achieved_score': writeScore,
|
|
'max_score': 20,
|
|
});
|
|
|
|
// 7. CPU Compute Speed (Max: 20 points)
|
|
final cpuTime = await PerformanceTester.testCPUSpeed();
|
|
int cpuScore;
|
|
if (cpuTime <= 1.0) {
|
|
cpuScore = 20;
|
|
} else if (cpuTime <= 2.5) {
|
|
cpuScore = 15;
|
|
} else if (cpuTime <= 4.0) {
|
|
cpuScore = 10;
|
|
} else {
|
|
cpuScore = 5;
|
|
}
|
|
details.add({
|
|
'label': 'سرعة المعالجة (${cpuTime.toStringAsFixed(2)} ثانية)',
|
|
'status': cpuScore >= 10,
|
|
'achieved_score': cpuScore,
|
|
'max_score': 20,
|
|
});
|
|
|
|
// 8. Memory Pressure (Max: 15 points)
|
|
final usedPercent = await _readUsedRamPercent();
|
|
int memScore;
|
|
if (usedPercent <= 60) {
|
|
memScore = 15;
|
|
} else if (usedPercent <= 80) {
|
|
memScore = 10;
|
|
} else if (usedPercent <= 90) {
|
|
memScore = 5;
|
|
} else {
|
|
memScore = 0;
|
|
}
|
|
details.add({
|
|
'label': 'استخدام الرام الحالي (${usedPercent.toStringAsFixed(0)}%)',
|
|
'status': memScore >= 10,
|
|
'achieved_score': memScore,
|
|
'max_score': 15,
|
|
});
|
|
|
|
// Calculate the final total score by summing up the achieved scores.
|
|
final totalScore = details.fold<int>(
|
|
0, (sum, item) => sum + (item['achieved_score'] as int));
|
|
|
|
return {
|
|
'score': totalScore.clamp(0, 100),
|
|
'details': details,
|
|
};
|
|
}
|
|
}
|