Skip to content
This repository was archived by the owner on Aug 25, 2024. It is now read-only.

Commit b070a3c

Browse files
authored
Merge pull request #195 from Sacha338/js-to-ts
Réécriture de l'entièreté des fichier JS du répertoire `/utils` en TS
2 parents 6af6d6f + 4e98074 commit b070a3c

File tree

8 files changed

+576
-273
lines changed

8 files changed

+576
-273
lines changed

utils/ColorCoursName.ts

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import SyncStorage from 'sync-storage';
2+
3+
SyncStorage.init();
4+
5+
const colors: string[] = [
6+
'#2667a9',
7+
'#76a10b',
8+
'#3498DB',
9+
'#1ABC9C',
10+
'#a01679',
11+
'#27AE60',
12+
'#156cd6',
13+
'#F39C12',
14+
'#E67E22',
15+
'#D35400',
16+
'#2C3E50',
17+
'#E74C3C',
18+
'#C0392B',
19+
'#8E44AD',
20+
'#ad4491',
21+
'#9f563b',
22+
'#920205',
23+
];
24+
25+
interface RGBColor {
26+
r: number;
27+
g: number;
28+
b: number;
29+
}
30+
31+
const rgbCache: { [hex: string]: RGBColor } = {};
32+
33+
function hexToRGB(_hex: string): RGBColor {
34+
if (rgbCache[_hex]) return rgbCache[_hex];
35+
36+
// Remove '#' if present
37+
const hex = _hex.replace('#', '');
38+
39+
// Split into RGB components
40+
const r = parseInt(hex.substring(0, 2), 16);
41+
const g = parseInt(hex.substring(2, 4), 16);
42+
const b = parseInt(hex.substring(4, 6), 16);
43+
44+
rgbCache[_hex] = { r, g, b };
45+
return { r, g, b };
46+
}
47+
48+
function calculateDistance(color1: RGBColor, color2: RGBColor): number {
49+
return Math.abs(color1.r - color2.r) + Math.abs(color1.g - color2.g) + Math.abs(color1.b - color2.b);
50+
}
51+
52+
function findClosestColor(hexColor: string, colorList: string[]): string {
53+
const inputColor = hexToRGB(hexColor);
54+
let closestColor: string | null = null;
55+
let closestDistance = Infinity;
56+
57+
for (const color of colorList) {
58+
const distance = calculateDistance(inputColor, hexToRGB(color));
59+
60+
if (distance < closestDistance) {
61+
closestColor = color;
62+
closestDistance = distance;
63+
}
64+
}
65+
66+
return closestColor!;
67+
}
68+
69+
function getClosestColor(hexColor: string): string {
70+
return findClosestColor(hexColor, colors);
71+
}
72+
73+
function getClosestCourseColor(courseName: string): string {
74+
// Fonction pour générer une valeur de hachage à partir du nom du cours
75+
function hashCode(str: string): number {
76+
let hash = 5;
77+
for (let i = 0; i < str.length; i++) {
78+
const char = str.charCodeAt(i) + 1;
79+
hash = (hash << 5) - hash + char;
80+
}
81+
return hash;
82+
}
83+
84+
// Générer une valeur de hachage à partir du nom du cours
85+
const hash = hashCode(courseName);
86+
87+
// Introduire des facteurs multiplicatifs pour augmenter la variété des couleurs7
88+
const multiplierR = 32;
89+
const multiplierG = 26;
90+
const multiplierB = 22;
91+
92+
// Calculer les composantes RVB de la couleur à partir de la valeur de hachage et des facteurs multiplicatifs
93+
const r = Math.abs(((hash * multiplierR * hash) / 0.7) % 231);
94+
const g = Math.abs(((hash * multiplierG * hash) / 1.6) % 213);
95+
const b = Math.abs(((hash * multiplierB * hash) / 0.5) % 246);
96+
97+
// Convertir les composantes RVB en format HEX
98+
const hexColor = `#${r.toString(16).padStart(2, '0')}${g
99+
.toString(16)
100+
.padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
101+
102+
return hexColor;
103+
}
104+
105+
function normalizeCoursName(courseName: string = ''): string {
106+
// remove accents and lowercase
107+
courseName = courseName
108+
?.normalize('NFD')
109+
?.replace(/[\u0300-\u036f]/g, '')
110+
.toLowerCase();
111+
// remove spaces
112+
courseName = courseName.replace(/\s/g, '');
113+
// remove special characters
114+
courseName = courseName.replace(/[^a-zA-Z0-9]/g, '');
115+
return courseName;
116+
}
117+
118+
function getSavedCourseColor(courseName: string, courseColor: string): string {
119+
let originalCourseName = courseName;
120+
courseName = normalizeCoursName(courseName);
121+
let savedColors = SyncStorage.get('savedColors');
122+
if (savedColors) {
123+
savedColors = JSON.parse(savedColors);
124+
} else {
125+
savedColors = {};
126+
}
127+
128+
if (savedColors[courseName] && savedColors[courseName].color) {
129+
return savedColors[courseName].color;
130+
}
131+
// find a color that is not used
132+
const color = getClosestColor(courseColor || getClosestCourseColor(courseName));
133+
savedColors[courseName] = {
134+
color: color,
135+
originalCourseName: originalCourseName,
136+
systemCourseName: courseName,
137+
};
138+
SyncStorage.set('savedColors', JSON.stringify(savedColors));
139+
return color;
140+
}
141+
142+
function forceSavedCourseColor(courseName: string, courseColor: string): string {
143+
courseName = normalizeCoursName(courseName);
144+
let savedColors = SyncStorage.get('savedColors');
145+
if (savedColors) {
146+
savedColors = JSON.parse(savedColors);
147+
} else {
148+
savedColors = {};
149+
}
150+
151+
const color = courseColor;
152+
savedColors[courseName].color = color;
153+
SyncStorage.set('savedColors', JSON.stringify(savedColors));
154+
return color;
155+
}
156+
157+
function getRandomColor(): string {
158+
const randomColor = colors[Math.floor(Math.random() * colors.length)];
159+
return randomColor;
160+
}
161+
162+
export default getClosestColor;
163+
export { getClosestCourseColor, getSavedCourseColor, forceSavedCourseColor, getRandomColor };

utils/CustomEtabRoomFormat.js renamed to utils/CustomEtabRoomFormat.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
function getEtabRoom(room = '') {
2-
// letter followed by 2 or 3 digits
1+
function getEtabRoom(room: string = ''): { building: string, room: string, other: string | null } | undefined {
2+
// lettre suivie de 2 ou 3 chiffres
33
const regex = /(?:[A-Z]) ?(?:\d{2,3})/;
44
const match = regex.exec(room.split(' ')[0]);
55
if (match) {

utils/EmojiCoursName.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { FC } from 'react';
2+
3+
interface GradeEmojiList {
4+
[key: string]: string;
5+
}
6+
7+
const getClosestGradeEmoji = (subjectName: string): string => {
8+
const gradeEmojiList: GradeEmojiList = {
9+
numerique: '💻',
10+
SI: '💻',
11+
SNT: '💻',
12+
travaux: '⚒',
13+
travail: '💼',
14+
moral: '⚖️',
15+
env: '🌿',
16+
sport: '🏀',
17+
EPS: '🏀',
18+
econo: '📈',
19+
francais: '📚',
20+
anglais: '🇬🇧',
21+
allemand: '🇩🇪',
22+
espagnol: '🇪🇸',
23+
latin: '🏛️',
24+
italien: '🇮🇹',
25+
histoire: '📜',
26+
EMC: '🤝',
27+
hist: '📜',
28+
llc: '🌍',
29+
scientifique: '🔬',
30+
arts: '🎨',
31+
philosophie: '🤔',
32+
math: '📐',
33+
phys: '🧪',
34+
accomp: '👨‍🏫',
35+
tech: '🔧',
36+
ingenieur: '🔧',
37+
musique: '🎼',
38+
musical: '🎼',
39+
classe: '🏫',
40+
vie: '🧬',
41+
SES: '💰',
42+
stage: '👔',
43+
œuvre: '🖼️',
44+
default: '📝',
45+
};
46+
47+
const subjectNameFormatted: string = subjectName
48+
.toLowerCase()
49+
?.normalize('NFD')
50+
.replace(/[\u0300-\u036f]/g, '');
51+
52+
// sort keys by length in descending order
53+
const sortedKeys: string[] = Object.keys(gradeEmojiList).sort((a, b) => b.length - a.length);
54+
55+
// get emoji with key in subject name
56+
const closest: string = sortedKeys.find((key) => subjectNameFormatted.includes(key)) || 'default';
57+
58+
return gradeEmojiList[closest];
59+
};
60+
61+
export default getClosestGradeEmoji;

utils/FormatCoursName.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const formatExceptions: Map<string, string> = new Map([
2+
// Please keep this list sorted alphabetically
3+
['accompagnemt. perso.', 'Accompagnement Personnalisé'],
4+
['at. professionnalis.', 'Attelier de Professionnalisation'],
5+
['bloc 1 smdsi', 'Bloc 1 Support et Mise à Disposition des Services Informatiques'],
6+
['bloc 2 sisr', 'Bloc 2 Solutions d’Infrastructure, Systèmes et Réseaux'],
7+
['bloc 2 slam', 'Bloc 2 Solutions Logicielles et Applications Métiers'],
8+
['bloc 3 tp', 'Bloc 3 Travaux Pratiques'],
9+
['cul.eco.jur.man.app.', 'Culture Économique, Juridique et Managériale Appliquée'],
10+
['culture gene.et expr', 'Culture générale et expression'],
11+
['cult.eco jur. manag.', 'Culture Économique, Juridique et Managériale'],
12+
['education civique', 'Éducation civique'],
13+
['enseign.scientifique', 'Enseignement scientifique'],
14+
['ed.physique & sport.', 'Éducation Physique et Sportive'],
15+
['education musicale', 'Éducation musicale'],
16+
['education physique et sportive', 'Éducation Physique et Sportive'],
17+
['eps', 'Éducation Physique et Sportive'],
18+
['francais', 'Français'],
19+
['histoire geo', 'Histoire-Géo'],
20+
['histoire-geo', 'Histoire-Géo'],
21+
['histoire & geograph.', 'Histoire-Géo'],
22+
['histoire-geographie', 'Histoire-Géographie'],
23+
['human.litter.philo', 'Humanités, Littérature & Philosophie'],
24+
['llc angl.mond.cont.', 'LLCER Anglais Monde Contemporain'],
25+
['maths pour informatq', 'Mathématiques pour l’informatique'],
26+
['mathematiques', 'Mathématiques'],
27+
['math 1ere', 'Mathématiques 1ère'],
28+
['numerique sc.inform.', 'Numérique et Sciences Informatiques'],
29+
['physique-chimie', 'Physique-Chimie'],
30+
['sc.econo & sociales', 'Sciences Économiques et Sociales'],
31+
['sciences de la vie et de la terre', 'Sciences de la Vie et de la Terre'],
32+
['sciences vie & terre', 'Sciences de la Vie et de la Terre'],
33+
['sciences economiques et sociales', 'Sciences Économiques et Sociales'],
34+
['sc.numeriq.technol.', 'Sciences Numériques et Technologie'],
35+
['vie de classe', 'Vie de classe'],
36+
]);
37+
38+
const lengthExceptions: Set<string> = new Set(['vie', 'de', 'des', 'et', 'la']);
39+
40+
function formatCoursName(name: string): string {
41+
let formattedName: string = name
42+
.split(' ')
43+
.map((word: string) => {
44+
if (word.length > 3 || lengthExceptions.has(word.toLowerCase())) {
45+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
46+
}
47+
return word;
48+
})
49+
.join(' ');
50+
51+
if (formatExceptions.has(formattedName.toLowerCase())) {
52+
formattedName = formatExceptions.get(formattedName.toLowerCase())!;
53+
}
54+
55+
return formattedName;
56+
}
57+
58+
export default formatCoursName;

utils/GetUIColors.js renamed to utils/GetUIColors.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,28 @@ import { useMemo } from 'react';
22
import { Platform, useColorScheme } from 'react-native';
33
import { useTheme } from 'react-native-paper';
44

5-
function useUIColors(schemeForce, platformForce) {
5+
interface UIColors {
6+
theme: string;
7+
dark: boolean;
8+
background: string;
9+
backgroundHigh: string;
10+
backgroundItems: string;
11+
modalBackground: string;
12+
element: string;
13+
elementHigh: string;
14+
text: string;
15+
primary: string;
16+
primaryBackground: string;
17+
border: string;
18+
borderLight: string;
19+
}
20+
21+
function useUIColors(schemeForce: string | undefined, platformForce: string | undefined): UIColors {
622
const theme = useTheme();
723
const scheme = useColorScheme();
824

9-
let isDark = scheme === 'dark';
10-
let platform = Platform.OS;
25+
let isDark: boolean = scheme === 'dark';
26+
let platform: string = Platform.OS;
1127

1228
if (schemeForce) {
1329
isDark = schemeForce === 'dark';
@@ -18,9 +34,9 @@ function useUIColors(schemeForce, platformForce) {
1834
}
1935

2036
return useMemo(() => {
21-
let background;
22-
let backgroundHigh;
23-
let backgroundItems;
37+
let background: string;
38+
let backgroundHigh: string;
39+
let backgroundItems: string;
2440

2541
if (platform === 'ios') {
2642
background = isDark ? '#0B0B0C' : '#ffffff';
@@ -32,13 +48,13 @@ function useUIColors(schemeForce, platformForce) {
3248
backgroundItems = theme.colors.elevation.level1;
3349
}
3450

35-
let modalBackground = background;
51+
let modalBackground: string = background;
3652
if (platform === 'ios') {
3753
modalBackground = isDark ? '#0B0B0C' : '#f2f2f7';
3854
}
3955

40-
let element;
41-
let elementHigh;
56+
let element: string;
57+
let elementHigh: string;
4258

4359
if (platform === 'ios') {
4460
element = isDark ? '#161618' : '#ffffff';
@@ -48,10 +64,10 @@ function useUIColors(schemeForce, platformForce) {
4864
elementHigh = theme.colors.elevation.level2;
4965
}
5066

51-
const text = isDark ? '#ffffff' : '#000000';
67+
const text: string = isDark ? '#ffffff' : '#000000';
5268

53-
let primaryBackground;
54-
let primary = '#32AB8E';
69+
let primaryBackground: string;
70+
let primary: string = '#32AB8E';
5571

5672
if (platform === 'android') {
5773
primary = theme.colors.primary;
@@ -63,8 +79,8 @@ function useUIColors(schemeForce, platformForce) {
6379
primaryBackground = theme.colors.primaryContainer;
6480
}
6581

66-
let borderColor;
67-
let borderColorLight;
82+
let borderColor: string;
83+
let borderColorLight: string;
6884

6985
if (isDark) {
7086
borderColor = '#444444';
@@ -92,4 +108,4 @@ function useUIColors(schemeForce, platformForce) {
92108
}, [isDark, platform, theme]);
93109
}
94110

95-
export default useUIColors;
111+
export default useUIColors;

0 commit comments

Comments
 (0)