Révision 6f451cc1
GES_PAC/App.xaml.cs | ||
---|---|---|
1 |
using GES_PAC.Model; |
|
2 |
using GES_PAC.ViewModel; |
|
3 |
using Microsoft.EntityFrameworkCore; |
|
4 |
|
|
1 | 5 |
namespace GES_PAC |
2 | 6 |
{ |
3 | 7 |
public partial class App : Application |
4 | 8 |
{ |
9 |
public static AppDbContext Db { get; private set; } |
|
5 | 10 |
public App() |
6 | 11 |
{ |
7 | 12 |
InitializeComponent(); |
13 |
|
|
14 |
//var dbPath = Path.Combine(FileSystem.AppDataDirectory, "GES_PAC.db3"); |
|
15 |
//if (File.Exists(dbPath)) |
|
16 |
// File.Delete(dbPath); |
|
17 |
|
|
18 |
|
|
19 |
Db = new AppDbContext(); |
|
20 |
Db.Database.EnsureCreated(); |
|
21 |
|
|
22 |
_ = InitSmartEnumsAsync(); |
|
23 |
//_ = InitDb(); |
|
8 | 24 |
} |
9 | 25 |
|
10 | 26 |
protected override Window CreateWindow(IActivationState? activationState) |
11 | 27 |
{ |
12 | 28 |
return new Window(new AppShell()); |
13 | 29 |
} |
30 |
|
|
31 |
public static async Task InitSmartEnumsAsync() |
|
32 |
{ |
|
33 |
foreach (var phase in PhaseCalibration.All) |
|
34 |
{ |
|
35 |
if (!await Db.PhaseCalibration.AnyAsync(p => p.Value == phase.Value)) |
|
36 |
Db.PhaseCalibration.Add(phase); |
|
37 |
} |
|
38 |
|
|
39 |
foreach (var type in TypeCalibration.All) |
|
40 |
{ |
|
41 |
if (!await Db.TypeCalibration.AnyAsync(t => t.Value == type.Value)) |
|
42 |
Db.TypeCalibration.Add(type); |
|
43 |
} |
|
44 |
|
|
45 |
foreach (var comportement in TypeComportement.All) |
|
46 |
{ |
|
47 |
if (!await Db.TypeComportement.AnyAsync(c => c.Value == comportement.Value)) |
|
48 |
Db.TypeComportement.Add(comportement); |
|
49 |
} |
|
50 |
|
|
51 |
await Db.SaveChangesAsync(); |
|
52 |
} |
|
53 |
|
|
54 |
|
|
55 |
|
|
56 |
private async Task InitDb() |
|
57 |
{ |
|
58 |
//ONLY FOR TESTS |
|
59 |
var place = new Lieu("Elevage Langlade", "INRAE", "Mouton"); |
|
60 |
var person = new Personne("Bond", "James", "jamesbond@inrae.fr"); |
|
61 |
await Db.Personne.AddAsync(person); |
|
62 |
await Db.Lieu.AddAsync(place); |
|
63 |
await Db.SaveChangesAsync(); |
|
64 |
//ONLY FOR TESTS |
|
65 |
} |
|
14 | 66 |
} |
15 | 67 |
} |
GES_PAC/GES_PAC.csproj | ||
---|---|---|
20 | 20 |
<SingleProject>true</SingleProject> |
21 | 21 |
<ImplicitUsings>enable</ImplicitUsings> |
22 | 22 |
<Nullable>enable</Nullable> |
23 |
<GenerateSatelliteAssemblies>false</GenerateSatelliteAssemblies> |
|
23 | 24 |
|
24 | 25 |
<!-- Display name --> |
25 | 26 |
<ApplicationTitle>GES_PAC</ApplicationTitle> |
... | ... | |
70 | 71 |
|
71 | 72 |
<ItemGroup> |
72 | 73 |
<PackageReference Include="CommunityToolkit.Maui" Version="9.1.1" /> |
74 |
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" /> |
|
73 | 75 |
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" /> |
74 | 76 |
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" /> |
77 |
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" /> |
|
75 | 78 |
</ItemGroup> |
76 | 79 |
|
77 | 80 |
<ItemGroup> |
GES_PAC/Model/Calibration.cs | ||
---|---|---|
1 |
|
|
1 |
using SQLite; |
|
2 |
using System.ComponentModel.DataAnnotations.Schema; |
|
2 | 3 |
|
3 | 4 |
namespace GES_PAC.Model |
4 | 5 |
{ |
5 | 6 |
public class Calibration |
6 | 7 |
{ |
7 |
public long Id { get; set; } |
|
8 |
#region Propri?t?s |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
11 |
public int PhaseCalibrationId { get; set; } |
|
12 |
[ForeignKey("PhaseCalibrationId")] |
|
8 | 13 |
public PhaseCalibration Phase { get; set; } |
9 |
public List<MesureCalibration> Mesures { get; set; } |
|
10 |
|
|
14 |
public List<MesureCalibration> Mesures { get; set; } = []; |
|
15 |
public int JourneeId { get; set; } |
|
16 |
[ForeignKey("JourneeId")] |
|
17 |
public Journee Journee { get; set; } |
|
18 |
#endregion |
|
19 |
|
|
20 |
#region Constructeurs |
|
21 |
public Calibration() { } |
|
11 | 22 |
public Calibration(PhaseCalibration Phase, MesureCalibration Mesure) |
12 | 23 |
{ |
13 | 24 |
this.Phase = Phase; |
14 | 25 |
Mesures = []; |
15 | 26 |
Mesures.Add(Mesure); |
16 | 27 |
} |
17 |
|
|
28 |
#endregion |
|
18 | 29 |
public void AddMesure(MesureCalibration mesure) |
19 | 30 |
{ |
31 |
mesure.Calibration = this; |
|
20 | 32 |
var index = Mesures.FindIndex(m => m.Type == mesure.Type); |
21 | 33 |
if (index != -1) |
22 | 34 |
{ |
GES_PAC/Model/Comportement.cs | ||
---|---|---|
1 | 1 |
|
2 |
using SQLite; |
|
3 |
using System.ComponentModel.DataAnnotations.Schema; |
|
4 |
|
|
2 | 5 |
namespace GES_PAC.Model |
3 | 6 |
{ |
4 | 7 |
public class Comportement |
5 | 8 |
{ |
6 |
public long Id { get; set; } |
|
9 |
#region Propri?t?s |
|
10 |
[PrimaryKey, AutoIncrement] |
|
11 |
public int Id { get; set; } |
|
12 |
public int SerieAnimalId { get; set; } |
|
13 |
[ForeignKey("SerieAnimalId")] |
|
14 |
public SerieAnimal SerieAnimal { get; set; } |
|
7 | 15 |
public DateTime Time { get; set; } |
16 |
public int TypeComportementId { get; set; } |
|
17 |
[ForeignKey("TypeComportementId")] |
|
8 | 18 |
public TypeComportement Type { get; set; } |
9 | 19 |
public string? Commentaire { get; set; } |
20 |
#endregion |
|
10 | 21 |
|
22 |
#region Constructeurs |
|
23 |
public Comportement() { } |
|
11 | 24 |
public Comportement(DateTime Time, TypeComportement Type, string Commentaire) |
12 | 25 |
{ |
13 | 26 |
this.Time = Time; |
14 | 27 |
this.Type = Type; |
15 | 28 |
this.Commentaire = Commentaire; |
16 | 29 |
} |
30 |
#endregion |
|
17 | 31 |
} |
18 | 32 |
} |
GES_PAC/Model/IMesureBase.cs | ||
---|---|---|
1 |
using SQLite; |
|
2 |
|
|
3 |
namespace GES_PAC.Model |
|
4 |
{ |
|
5 |
internal interface IMesureBase |
|
6 |
{ |
|
7 |
#region Propriétés |
|
8 |
public int Id { get; set; } |
|
9 |
public DateTime Time { get; set; } |
|
10 |
public double Conc_O2 { get; set; } |
|
11 |
public double Conc_CO2 { get; set; } |
|
12 |
public double Conc_CH4 { get; set; } |
|
13 |
#endregion |
|
14 |
} |
|
15 |
} |
GES_PAC/Model/Journee.cs | ||
---|---|---|
1 |
using SQLite; |
|
2 |
using System.ComponentModel.DataAnnotations.Schema; |
|
3 |
|
|
1 | 4 |
namespace GES_PAC.Model |
2 | 5 |
{ |
3 | 6 |
public class Journee |
4 | 7 |
{ |
5 | 8 |
#region Propriétés |
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
11 |
public int PersonneId { get; set; } |
|
12 |
[ForeignKey("PersonneId")] |
|
6 | 13 |
public Personne Responsable { get; set; } |
14 |
public int LieuId { get; set; } |
|
15 |
[ForeignKey("LieuId")] |
|
7 | 16 |
public Lieu Lieu { get; set; } |
8 |
public long Id { get; set; } |
|
9 | 17 |
public DateTime Date { get; set; } |
10 | 18 |
public string Regime { get; set; } |
11 |
public List<Serie> Series { get; set; } |
|
12 |
public List<Calibration> Calibrations { get; set; } |
|
19 |
public List<Serie> Series { get; set; } = [];
|
|
20 |
public List<Calibration> Calibrations { get; set; } = [];
|
|
13 | 21 |
#endregion |
14 | 22 |
|
15 | 23 |
#region Constructeurs |
24 |
public Journee(){} |
|
16 | 25 |
public Journee(DateTime Date, Personne Responsable, Lieu Lieu, string Regime) |
17 | 26 |
{ |
18 | 27 |
this.Responsable = Responsable; |
... | ... | |
25 | 34 |
#endregion |
26 | 35 |
|
27 | 36 |
#region Méthodes |
28 |
public bool AddCalibration(MesureCalibration mesureCalibration, PhaseCalibration phaseCalibration) |
|
29 |
{ |
|
30 |
var existing = Calibrations.FirstOrDefault(c => c.Phase == phaseCalibration); |
|
31 |
|
|
32 |
if (existing == null) |
|
33 |
{ |
|
34 |
Calibrations.Add(new Calibration(phaseCalibration, mesureCalibration)); |
|
35 |
return false; |
|
36 |
} |
|
37 |
|
|
38 |
existing.AddMesure(mesureCalibration); |
|
39 |
return existing.IsComplete(); |
|
40 |
} |
|
41 | 37 |
|
42 | 38 |
public void AddSet(Serie set) |
43 | 39 |
{ |
40 |
set.Journee = this; |
|
44 | 41 |
Series.Add(set); |
45 | 42 |
} |
46 |
|
|
47 |
public PhaseCalibration GetCurrentPhase() |
|
43 |
public List<TypeCalibration> GetMissingCalibrationByPhase(PhaseCalibration phase) |
|
48 | 44 |
{ |
49 |
if (Series.Count == 0) |
|
50 |
{ |
|
51 |
return PhaseCalibration.DEBUT; |
|
52 |
} |
|
53 |
return PhaseCalibration.FIN; |
|
54 |
} |
|
45 |
if (phase == null) |
|
46 |
return TypeCalibration.All; |
|
55 | 47 |
|
56 |
public Calibration GetCurrentCalibration() |
|
57 |
{ |
|
58 |
return Calibrations.FirstOrDefault(c => c.Phase == GetCurrentPhase()); |
|
59 |
} |
|
48 |
var calibPhase = Calibrations.FirstOrDefault(c => c.Phase == phase); |
|
60 | 49 |
|
61 |
public List<TypeCalibration> GetCurrentMissingCalibration() |
|
62 |
{ |
|
63 |
if (Calibrations.Count == 0 || Calibrations.Last().IsComplete()) |
|
64 |
{ |
|
50 |
if (calibPhase == null || calibPhase.IsComplete()) |
|
65 | 51 |
return TypeCalibration.All; |
66 |
} |
|
67 |
return TypeCalibration.All.Except(Calibrations.Last().GetTypesDone()).ToList();
|
|
52 |
|
|
53 |
return TypeCalibration.All.Except(calibPhase.GetTypesDone()).ToList();
|
|
68 | 54 |
} |
69 |
|
|
70 |
public Serie GetCurrentSet() |
|
55 |
|
|
56 |
|
|
57 |
public Serie? GetCurrentSet() |
|
71 | 58 |
{ |
72 |
return Series.LastOrDefault(); |
|
59 |
return Series?.LastOrDefault();
|
|
73 | 60 |
} |
74 | 61 |
public bool HasAnySet() |
75 | 62 |
{ |
... | ... | |
99 | 86 |
} |
100 | 87 |
internal Calibration GetDebutCalibration() |
101 | 88 |
{ |
102 |
return Calibrations.FirstOrDefault(c => c.Phase == PhaseCalibration.DEBUT);
|
|
89 |
return Calibrations.FirstOrDefault(c => c.Phase?.Value == PhaseCalibration.DEBUT.Value);
|
|
103 | 90 |
} |
104 | 91 |
internal bool IsCalibrationComplete(PhaseCalibration pc) |
105 | 92 |
{ |
106 |
return Calibrations.FirstOrDefault(c => c.Phase == pc)?.IsComplete() ?? false; |
|
93 |
return Calibrations?.FirstOrDefault(c => c.Phase == pc)?.IsComplete() ?? false;
|
|
107 | 94 |
} |
108 | 95 |
internal bool IsComplete() |
109 | 96 |
{ |
110 |
return Calibrations.FirstOrDefault(c => c.Phase == PhaseCalibration.FIN)?.IsComplete() ?? false; |
|
97 |
return Calibrations?.FirstOrDefault(c => c.Phase == PhaseCalibration.FIN)?.IsComplete() ?? false; |
|
98 |
} |
|
99 |
|
|
100 |
internal void AddCalibration(Calibration calibration) |
|
101 |
{ |
|
102 |
calibration.Journee = this; |
|
103 |
Calibrations.Add(calibration); |
|
111 | 104 |
} |
112 | 105 |
#endregion |
113 | 106 |
} |
GES_PAC/Model/Lieu.cs | ||
---|---|---|
1 | 1 |
|
2 |
using SQLite; |
|
3 |
|
|
2 | 4 |
namespace GES_PAC.Model |
3 | 5 |
{ |
4 | 6 |
public class Lieu |
5 | 7 |
{ |
6 |
public long Id { get; set; } |
|
8 |
#region Propri?t?s |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
7 | 11 |
public string Nom { get; set; } |
8 | 12 |
public string Client { get; set; } |
9 | 13 |
public string Espece { get; set; } |
14 |
#endregion |
|
10 | 15 |
|
16 |
#region Constructeurs |
|
17 |
public Lieu() { } |
|
11 | 18 |
public Lieu(string nom, string client, string espece) |
12 | 19 |
{ |
13 | 20 |
Nom = nom; |
14 | 21 |
Client = client; |
15 | 22 |
Espece = espece; |
16 | 23 |
} |
24 |
#endregion |
|
17 | 25 |
|
18 | 26 |
public override string ToString() |
19 | 27 |
{ |
GES_PAC/Model/Mesure.cs | ||
---|---|---|
1 | 1 |
|
2 |
using SQLite; |
|
3 |
using System.ComponentModel.DataAnnotations.Schema; |
|
4 |
|
|
2 | 5 |
namespace GES_PAC.Model |
3 | 6 |
{ |
4 |
public class Mesure |
|
7 |
public class Mesure : IMesureBase
|
|
5 | 8 |
{ |
6 |
public long Id { get; set; } |
|
9 |
#region Propri?t?s |
|
10 |
[PrimaryKey, AutoIncrement] |
|
11 |
public int Id { get; set; } |
|
7 | 12 |
public DateTime Time { get; set; } |
8 | 13 |
public double Conc_O2 { get; set; } |
9 | 14 |
public double Conc_CO2 { get; set; } |
10 | 15 |
public double Conc_CH4 { get; set; } |
16 |
public int SerieAnimalId { get; set; } |
|
17 |
[ForeignKey("SerieAnimalId")] |
|
18 |
public SerieAnimal SerieAnimal { get; set; } |
|
19 |
#endregion |
|
11 | 20 |
|
21 |
#region Constructeurs |
|
22 |
public Mesure() { } |
|
12 | 23 |
public Mesure(DateTime Time, double Conc_O2, double Conc_CO2, double Conc_CH4) |
13 | 24 |
{ |
14 | 25 |
this.Time = Time; |
... | ... | |
16 | 27 |
this.Conc_CO2 = Conc_CO2; |
17 | 28 |
this.Conc_CH4 = Conc_CH4; |
18 | 29 |
} |
30 |
#endregion |
|
19 | 31 |
} |
20 | 32 |
} |
GES_PAC/Model/MesureCalibration.cs | ||
---|---|---|
1 |
using SQLite; |
|
2 |
using System.ComponentModel.DataAnnotations.Schema; |
|
1 | 3 |
|
2 | 4 |
namespace GES_PAC.Model |
3 | 5 |
{ |
4 |
public class MesureCalibration : Mesure
|
|
6 |
public class MesureCalibration : IMesureBase
|
|
5 | 7 |
{ |
8 |
#region Propri?t?s |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
11 |
public DateTime Time { get; set; } |
|
12 |
public double Conc_O2 { get; set; } |
|
13 |
public double Conc_CO2 { get; set; } |
|
14 |
public double Conc_CH4 { get; set; } |
|
15 |
public int TypeCalibrationId { get; set; } |
|
16 |
[ForeignKey("TypeCalibrationId")] |
|
6 | 17 |
public TypeCalibration Type { get; set; } |
7 |
public string RefBouteille { get; set; } |
|
18 |
public string? RefBouteille { get; set; } |
|
19 |
public int CalibrationId { get; set; } |
|
20 |
[ForeignKey("CalibrationId")] |
|
21 |
public Calibration Calibration { get; set; } |
|
8 | 22 |
|
9 |
public MesureCalibration(DateTime Time, double Conc_O2, double Conc_CO2, double Conc_CH4, TypeCalibration Type, string RefBouteille) : base(Time, Conc_O2, Conc_CO2, Conc_CH4) |
|
23 |
#endregion |
|
24 |
|
|
25 |
#region Constructeurs |
|
26 |
public MesureCalibration() { } |
|
27 |
public MesureCalibration(DateTime Time, double Conc_O2, double Conc_CO2, double Conc_CH4, TypeCalibration Type, string RefBouteille) |
|
10 | 28 |
{ |
29 |
this.Time = Time; |
|
30 |
this.Conc_O2 = Conc_O2; |
|
31 |
this.Conc_CO2 = Conc_CO2; |
|
32 |
this.Conc_CH4 = Conc_CH4; |
|
11 | 33 |
this.Type = Type; |
12 | 34 |
if (Type.Value != 0) |
13 | 35 |
{ |
14 | 36 |
this.RefBouteille = RefBouteille; |
15 | 37 |
} |
16 | 38 |
} |
39 |
#endregion |
|
17 | 40 |
} |
18 | 41 |
} |
GES_PAC/Model/Personne.cs | ||
---|---|---|
1 | 1 |
|
2 |
using SQLite; |
|
3 |
|
|
2 | 4 |
namespace GES_PAC.Model |
3 | 5 |
{ |
4 | 6 |
public class Personne |
5 | 7 |
{ |
6 |
public long Id { get; set; } |
|
8 |
#region Propri?t?s |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
7 | 11 |
public string? Nom { get; set; } |
8 | 12 |
public string? Prenom { get; set; } |
9 | 13 |
public string? Email { get; set; } |
14 |
#endregion |
|
10 | 15 |
|
11 |
|
|
16 |
#region Constructeurs |
|
12 | 17 |
public Personne() { } |
13 | 18 |
public Personne(string Nom, string Prenom, string Email) |
14 | 19 |
{ |
... | ... | |
16 | 21 |
this.Prenom = Prenom; |
17 | 22 |
this.Email = Email; |
18 | 23 |
} |
24 |
#endregion |
|
19 | 25 |
public override string ToString() |
20 | 26 |
{ |
21 | 27 |
return $"{Nom} {Prenom}"; |
GES_PAC/Model/PhaseCalibration.cs | ||
---|---|---|
1 |
using SQLite; |
|
2 |
|
|
1 | 3 |
namespace GES_PAC.Model |
2 | 4 |
{ |
3 | 5 |
public class PhaseCalibration |
4 | 6 |
{ |
5 |
public string Name { get; } |
|
6 |
public int Value { get; } |
|
7 |
#region Propri?t?s |
|
8 |
[PrimaryKey, AutoIncrement] |
|
9 |
public int Id { get; set; } |
|
10 |
public string Name { get; set; } |
|
11 |
public int Value { get; set; } |
|
12 |
#endregion |
|
7 | 13 |
|
14 |
#region Constructeurs |
|
15 |
public PhaseCalibration() { } |
|
8 | 16 |
private PhaseCalibration(string name, int value) |
9 | 17 |
{ |
10 | 18 |
Name = name; |
11 | 19 |
Value = value; |
12 | 20 |
} |
21 |
#endregion |
|
13 | 22 |
|
14 | 23 |
public static readonly PhaseCalibration DEBUT = new("d?but", 1); |
15 | 24 |
public static readonly PhaseCalibration FIN = new("fin", 2); |
GES_PAC/Model/Serie.cs | ||
---|---|---|
1 |
|
|
2 |
using System.Collections.ObjectModel;
|
|
1 |
using SQLite; |
|
2 |
using System.ComponentModel.DataAnnotations.Schema;
|
|
3 | 3 |
|
4 | 4 |
namespace GES_PAC.Model |
5 | 5 |
{ |
6 | 6 |
public class Serie |
7 | 7 |
{ |
8 | 8 |
#region Propriétés |
9 |
public long Id { get; set; } |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
11 |
public int JourneeId { get; set; } |
|
12 |
[ForeignKey("JourneeId")] |
|
13 |
public Journee Journee { get; set; } |
|
10 | 14 |
public DateTime Time { get; set; } |
11 | 15 |
public DateTime MiseAJeun { get; set; } |
12 | 16 |
public double Temperature { get; set; } |
... | ... | |
16 | 20 |
#endregion |
17 | 21 |
|
18 | 22 |
#region Constructeurs |
23 |
public Serie() { } |
|
19 | 24 |
public Serie(DateTime Time, DateTime MiseAJeun, double Temperature, double Humidite, double Pression) |
20 | 25 |
{ |
21 | 26 |
this.Time = Time; |
... | ... | |
30 | 35 |
#region Méthodes |
31 | 36 |
public void AddSerieAnimal(SerieAnimal serieAnimal) |
32 | 37 |
{ |
38 |
serieAnimal.Serie = this; |
|
33 | 39 |
var existing = SeriesAnimales.FirstOrDefault(s => s.NumeroBoite == serieAnimal.NumeroBoite); |
34 | 40 |
if (existing != null) |
35 | 41 |
SeriesAnimales.Remove(existing); |
GES_PAC/Model/SerieAnimal.cs | ||
---|---|---|
1 | 1 |
|
2 |
using Microsoft.Maui.Layouts; |
|
2 |
using SQLite; |
|
3 |
using System.ComponentModel.DataAnnotations.Schema; |
|
3 | 4 |
|
4 | 5 |
namespace GES_PAC.Model |
5 | 6 |
{ |
6 | 7 |
public class SerieAnimal |
7 | 8 |
{ |
8 |
public long Id { get; set; } |
|
9 |
#region Propriétés |
|
10 |
[PrimaryKey, AutoIncrement] |
|
11 |
public int Id { get; set; } |
|
9 | 12 |
public int NumeroBoite { get; set; } |
10 | 13 |
public double Poids { get; set; } |
11 | 14 |
public DateTime DatePesee { get; set; } |
12 | 15 |
public string RFID { get; set; } |
13 | 16 |
public List<Mesure> Mesures { get; set; } |
14 | 17 |
public List<Comportement> Comportements { get; set; } |
18 |
public int SerieId { get; set; } |
|
19 |
[ForeignKey("SerieId")] |
|
20 |
public Serie Serie { get; set; } |
|
15 | 21 |
public bool IsOut { get; set; } = false; |
22 |
#endregion |
|
16 | 23 |
|
24 |
#region Constructeurs |
|
25 |
public SerieAnimal() { } |
|
17 | 26 |
public SerieAnimal(int numeroBoite, double poids, DateTime datePesee, string rFID) |
18 | 27 |
{ |
19 | 28 |
NumeroBoite = numeroBoite; |
... | ... | |
23 | 32 |
Mesures = []; |
24 | 33 |
Comportements = []; |
25 | 34 |
} |
35 |
#endregion |
|
26 | 36 |
|
27 | 37 |
public int GetMeasureCount() |
28 | 38 |
{ |
... | ... | |
31 | 41 |
|
32 | 42 |
internal void AddMeasure(Mesure newMeasure) |
33 | 43 |
{ |
44 |
newMeasure.SerieAnimal = this; |
|
34 | 45 |
Mesures.Add(newMeasure); |
35 | 46 |
} |
36 | 47 |
|
... | ... | |
45 | 56 |
|
46 | 57 |
public void AddBehaviour(Comportement newBehaviour) |
47 | 58 |
{ |
59 |
newBehaviour.SerieAnimal = this; |
|
48 | 60 |
Comportements.Add(newBehaviour); |
49 | 61 |
} |
50 | 62 |
|
GES_PAC/Model/TypeCalibration.cs | ||
---|---|---|
1 |
using SQLite; |
|
2 |
|
|
1 | 3 |
namespace GES_PAC.Model |
2 | 4 |
{ |
3 | 5 |
public class TypeCalibration |
4 | 6 |
{ |
5 |
public string Name { get; } |
|
6 |
public int Value { get; } |
|
7 |
#region Propri?t?s |
|
8 |
[PrimaryKey, AutoIncrement] |
|
9 |
public int Id { get; set; } |
|
10 |
public string Name { get; set; } |
|
11 |
public int Value { get; set; } |
|
12 |
#endregion |
|
7 | 13 |
|
8 |
private TypeCalibration(string name, int value) // a passer en public quand integration webservice |
|
14 |
#region Constructeurs |
|
15 |
public TypeCalibration() { } |
|
16 |
private TypeCalibration(string name, int value) |
|
9 | 17 |
{ |
10 | 18 |
Name = name; |
11 | 19 |
Value = value; |
12 | 20 |
} |
21 |
#endregion |
|
13 | 22 |
|
14 |
public static readonly TypeCalibration Air = new("AIR", 0);
|
|
15 |
public static readonly TypeCalibration Methane = new("METHANE", 1);
|
|
16 |
public static readonly TypeCalibration Melange = new("MELANGE", 2);
|
|
23 |
public static readonly TypeCalibration AIR = new("Air", 0);
|
|
24 |
public static readonly TypeCalibration METHANE = new("M?thane", 1);
|
|
25 |
public static readonly TypeCalibration MELANGE = new("M?lange", 2);
|
|
17 | 26 |
|
18 |
public static readonly List<TypeCalibration> All = new() { Air, Methane, Melange };
|
|
27 |
public static readonly List<TypeCalibration> All = new() { AIR, METHANE, MELANGE };
|
|
19 | 28 |
|
20 | 29 |
public override string ToString() => Name; |
21 | 30 |
} |
GES_PAC/Model/TypeComportement.cs | ||
---|---|---|
1 | 1 |
|
2 |
using SQLite; |
|
3 |
|
|
2 | 4 |
namespace GES_PAC.Model |
3 | 5 |
{ |
4 | 6 |
public class TypeComportement |
5 | 7 |
{ |
6 |
public string Name { get; } |
|
7 |
public int Value { get; } |
|
8 |
#region Propri?t?s |
|
9 |
[PrimaryKey, AutoIncrement] |
|
10 |
public int Id { get; set; } |
|
11 |
public string Name { get; set; } |
|
12 |
public int Value { get; set; } |
|
13 |
#endregion |
|
8 | 14 |
|
15 |
#region Constructeurs |
|
16 |
public TypeComportement() { } |
|
9 | 17 |
private TypeComportement(string name, int value) |
10 | 18 |
{ |
11 | 19 |
Name = name; |
12 | 20 |
Value = value; |
13 | 21 |
} |
22 |
#endregion |
|
14 | 23 |
|
15 | 24 |
public static readonly TypeComportement IMMOBILITE = new("Immobilit?", 1); |
16 | 25 |
public static readonly TypeComportement DEPLACEMENT_AVANT_ARRIERE = new("D?placement avant/arri?re", 2); |
GES_PAC/Platforms/Android/AndroidFileHelper.cs | ||
---|---|---|
11 | 11 |
|
12 | 12 |
ContentValues values = new ContentValues(); |
13 | 13 |
values.Put(MediaStore.IMediaColumns.DisplayName, fileName); |
14 |
values.Put(MediaStore.IMediaColumns.MimeType, "text/json");
|
|
14 |
values.Put(MediaStore.IMediaColumns.MimeType, "application/json");
|
|
15 | 15 |
|
16 | 16 |
values.Put(MediaStore.IMediaColumns.RelativePath, $"{Android.OS.Environment.DirectoryDownloads}/GES_PAC"); |
17 | 17 |
|
GES_PAC/Services/AppDbContext.cs | ||
---|---|---|
1 |
using Microsoft.EntityFrameworkCore; |
|
2 |
using GES_PAC.Model; |
|
3 |
|
|
4 |
public class AppDbContext : DbContext |
|
5 |
{ |
|
6 |
public AppDbContext() { } |
|
7 |
|
|
8 |
public DbSet<Calibration> Calibration { get; set; } |
|
9 |
public DbSet<Comportement> Comportement { get; set; } |
|
10 |
public DbSet<Journee> Journee { get; set; } |
|
11 |
public DbSet<Lieu> Lieu { get; set; } |
|
12 |
public DbSet<Mesure> Mesure { get; set; } |
|
13 |
public DbSet<MesureCalibration> MesureCalibration { get; set; } |
|
14 |
public DbSet<Personne> Personne { get; set; } |
|
15 |
public DbSet<PhaseCalibration> PhaseCalibration { get; set; } |
|
16 |
public DbSet<Serie> Serie { get; set; } |
|
17 |
public DbSet<SerieAnimal> SerieAnimal { get; set; } |
|
18 |
public DbSet<TypeCalibration> TypeCalibration { get; set; } |
|
19 |
public DbSet<TypeComportement> TypeComportement { get; set; } |
|
20 |
|
|
21 |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
|
22 |
{ |
|
23 |
string dbPath = Path.Combine(FileSystem.AppDataDirectory, "GES_PAC.db3"); |
|
24 |
optionsBuilder.UseSqlite($"Filename={dbPath}"); |
|
25 |
} |
|
26 |
|
|
27 |
protected override void OnModelCreating(ModelBuilder modelBuilder) |
|
28 |
{ |
|
29 |
|
|
30 |
} |
|
31 |
} |
GES_PAC/ViewModel/CreateBehaviourViewModel.cs | ||
---|---|---|
93 | 93 |
var currentSet = JourneeViewModel.Instance.GetCurrentDay().GetCurrentSet(); |
94 | 94 |
currentSet.AddBehaviour(newBehaviour, ChamberId, IsAnimalOut); |
95 | 95 |
|
96 |
App.Db.Comportement.Add(newBehaviour); |
|
97 |
await App.Db.SaveChangesAsync(); |
|
98 |
|
|
96 | 99 |
await Shell.Current.Navigation.PopToRootAsync(); |
97 | 100 |
IsBusy = false; |
98 | 101 |
} |
GES_PAC/ViewModel/CreateCalibrationViewModel.cs | ||
---|---|---|
1 | 1 |
using GES_PAC.Model; |
2 | 2 |
using GES_PAC.View; |
3 |
using Microsoft.EntityFrameworkCore; |
|
3 | 4 |
using System.Collections.ObjectModel; |
4 | 5 |
using System.Windows.Input; |
5 | 6 |
|
... | ... | |
11 | 12 |
|
12 | 13 |
#region Attributs |
13 | 14 |
public string _phaseName; |
15 |
private ObservableCollection<TypeCalibration> _typeCalibrations; |
|
14 | 16 |
private TypeCalibration _selectedType; |
15 | 17 |
private double? _conc_o2; |
16 | 18 |
private double? _conc_co2; |
... | ... | |
36 | 38 |
get => _phaseName; |
37 | 39 |
set |
38 | 40 |
{ |
41 |
if (_phaseName == value) return; |
|
39 | 42 |
_phaseName = value; |
40 | 43 |
Phase = PhaseCalibration.All.FirstOrDefault(p => p.Name == value) ?? PhaseCalibration.DEBUT; |
41 | 44 |
OnPropertyChanged(); |
45 |
OnPhaseChanged(); |
|
42 | 46 |
} |
43 | 47 |
} |
44 |
public ObservableCollection<TypeCalibration> TypeCalibrations { get; } |
|
48 |
public ObservableCollection<TypeCalibration> TypeCalibrations |
|
49 |
{ |
|
50 |
get => _typeCalibrations; |
|
51 |
set |
|
52 |
{ |
|
53 |
_typeCalibrations = value; |
|
54 |
OnPropertyChanged(); |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
45 | 58 |
public TypeCalibration SelectedType |
46 | 59 |
{ |
47 | 60 |
get => _selectedType; |
48 | 61 |
set |
49 | 62 |
{ |
50 | 63 |
_selectedType = value; |
51 |
IsRefBouteilleVisible = _selectedType != TypeCalibration.Air;
|
|
64 |
IsRefBouteilleVisible = _selectedType != TypeCalibration.AIR;
|
|
52 | 65 |
OnPropertyChanged(); |
53 | 66 |
OnTypeChanged(); |
54 | 67 |
ValidateForm(); |
... | ... | |
173 | 186 |
public CreateCalibrationViewModel() |
174 | 187 |
{ |
175 | 188 |
CreateCalibrationCommand = new Command(async () => await CreateCalibration()); |
189 |
} |
|
190 |
#endregion |
|
176 | 191 |
|
192 |
#region Méthodes |
|
193 |
|
|
194 |
public void OnPhaseChanged() |
|
195 |
{ |
|
177 | 196 |
var journeeActuelle = JourneeViewModel.Instance.GetCurrentDay(); |
178 |
var typesManquants = journeeActuelle.GetCurrentMissingCalibration(); |
|
179 |
var phaseCalibration = journeeActuelle.GetCurrentPhase(); |
|
197 |
var typesManquants = journeeActuelle.GetMissingCalibrationByPhase(Phase); |
|
180 | 198 |
|
181 | 199 |
TypeCalibrations = new ObservableCollection<TypeCalibration>(typesManquants); |
182 | 200 |
SelectedType = TypeCalibrations[0]; |
183 | 201 |
|
184 |
if (journeeActuelle.GetCurrentPhase() == PhaseCalibration.FIN)
|
|
185 |
{
|
|
202 |
if (Phase == PhaseCalibration.FIN)
|
|
203 |
{ |
|
186 | 204 |
LastCalibration = journeeActuelle.GetDebutCalibration(); |
187 | 205 |
HasLastMeasure = true; |
206 |
OnTypeChanged(); |
|
188 | 207 |
} |
189 | 208 |
} |
190 |
#endregion |
|
191 |
|
|
192 |
#region Méthodes |
|
193 | 209 |
private async Task CreateCalibration() |
194 | 210 |
{ |
195 | 211 |
if (IsBusy) return; |
196 | 212 |
IsBusy = true; |
197 | 213 |
|
214 |
var journee = JourneeViewModel.Instance.GetCurrentDay(); |
|
198 | 215 |
var date = DateTime.Now; |
199 | 216 |
var newCalib = new MesureCalibration(date, ConcO2 ?? 0, ConcCO2 ?? 0, ConcCH4 ?? 0, SelectedType, RefBouteille); |
200 |
var isComplete = JourneeViewModel.Instance.GetCurrentDay().AddCalibration(newCalib, Phase); |
|
201 | 217 |
|
218 |
var calibration = journee.Calibrations.FirstOrDefault(c => c.Phase == Phase); |
|
219 |
if (calibration == null) |
|
220 |
{ |
|
221 |
calibration = new Calibration(Phase, newCalib); |
|
222 |
journee.AddCalibration(calibration); |
|
223 |
App.Db.Calibration.Add(calibration); |
|
224 |
} |
|
225 |
else |
|
226 |
{ |
|
227 |
calibration.AddMesure(newCalib); |
|
228 |
} |
|
229 |
|
|
230 |
App.Db.MesureCalibration.Add(newCalib); |
|
231 |
await App.Db.SaveChangesAsync(); |
|
232 |
|
|
233 |
var isComplete = calibration.IsComplete(); |
|
202 | 234 |
var targetView = $"{nameof(CreateCalibrationView)}?phase={PhaseName}"; |
203 | 235 |
if (isComplete) { |
204 | 236 |
targetView = Phase == PhaseCalibration.DEBUT ? nameof(SetListView) : nameof(MainView); |
GES_PAC/ViewModel/CreateDayViewModel.cs | ||
---|---|---|
90 | 90 |
IsBusy = true; |
91 | 91 |
var date = DateTime.Now; |
92 | 92 |
var newDay = new Journee(date, SelectedPerson, SelectedPlace, Regime); |
93 |
App.Db.Journee.Add(newDay); |
|
94 |
await App.Db.SaveChangesAsync(); |
|
93 | 95 |
JourneeViewModel.Instance.Journees.Add(newDay); |
94 | 96 |
await Shell.Current.GoToAsync($"{nameof(CreateCalibrationView)}?phase={PhaseCalibration.DEBUT.Name}"); |
95 | 97 |
IsBusy = false; |
GES_PAC/ViewModel/CreateMeasureViewModel.cs | ||
---|---|---|
198 | 198 |
var currentSet = JourneeViewModel.Instance.GetCurrentDay().GetCurrentSet(); |
199 | 199 |
currentSet.AddMeasure(newMeasure, ChamberId, IsAnimalOut); |
200 | 200 |
|
201 |
App.Db.Mesure.Add(newMeasure); |
|
202 |
await App.Db.SaveChangesAsync(); |
|
203 |
|
|
201 | 204 |
await Shell.Current.Navigation.PopToRootAsync(); |
202 | 205 |
IsBusy = false; |
203 | 206 |
} |
GES_PAC/ViewModel/CreatePersonViewModel.cs | ||
---|---|---|
76 | 76 |
private async Task CreatePerson() |
77 | 77 |
{ |
78 | 78 |
var newTechnician = new Personne(Nom, Prenom, Email); |
79 |
App.Db.Personne.Add(newTechnician); |
|
80 |
await App.Db.SaveChangesAsync(); |
|
81 |
|
|
79 | 82 |
PersonViewModel.Instance.Persons.Add(newTechnician); |
80 | 83 |
await Shell.Current.GoToAsync("//Main"); |
81 | 84 |
} |
GES_PAC/ViewModel/CreatePlaceViewModel.cs | ||
---|---|---|
88 | 88 |
private async Task CreatePlace() |
89 | 89 |
{ |
90 | 90 |
var newPlace = new Lieu(Nom, Client, Espece); |
91 |
App.Db.Lieu.Add(newPlace); |
|
92 |
await App.Db.SaveChangesAsync(); |
|
93 |
|
|
91 | 94 |
PlaceViewModel.Instance.Places.Add(newPlace); |
92 | 95 |
await Shell.Current.GoToAsync("//Main"); |
93 | 96 |
} |
GES_PAC/ViewModel/CreateSetViewModel.cs | ||
---|---|---|
1 | 1 |
using GES_PAC.Model; |
2 |
using GES_PAC.View; |
|
3 | 2 |
using System.Windows.Input; |
4 | 3 |
|
5 | 4 |
namespace GES_PAC.ViewModel |
... | ... | |
104 | 103 |
var newSet = new Serie(date, DateTimeMAJ, Temperature ?? 0, Humidite ?? 0, Pression ?? 0); |
105 | 104 |
journeeActuelle.AddSet(newSet); |
106 | 105 |
|
106 |
App.Db.Serie.Add(newSet); |
|
107 |
await App.Db.SaveChangesAsync(); |
|
108 |
|
|
107 | 109 |
await Shell.Current.Navigation.PopToRootAsync(); |
108 | 110 |
IsBusy = false; |
109 | 111 |
} |
GES_PAC/ViewModel/EnterAnimalViewModel.cs | ||
---|---|---|
89 | 89 |
var newAnimalSet = new SerieAnimal(ChamberId, Poids ?? 0, date, NumRFID); |
90 | 90 |
journeeActuelle.GetCurrentSet().AddSerieAnimal(newAnimalSet); |
91 | 91 |
|
92 |
App.Db.SerieAnimal.Add(newAnimalSet); |
|
93 |
await App.Db.SaveChangesAsync(); |
|
94 |
|
|
92 | 95 |
await Shell.Current.GoToAsync($"{nameof(CreateMeasureView)}?chamberId={ChamberId}"); |
93 | 96 |
IsBusy = false; |
94 | 97 |
} |
GES_PAC/ViewModel/ExportDataViewModel.cs | ||
---|---|---|
3 | 3 |
using GES_PAC.Helpers; |
4 | 4 |
using System.Text.Json; |
5 | 5 |
using System.Collections.ObjectModel; |
6 |
using System.Text.Json.Serialization; |
|
6 | 7 |
|
7 | 8 |
|
8 | 9 |
namespace GES_PAC.ViewModel |
... | ... | |
61 | 62 |
IsBusy = true; |
62 | 63 |
var lastDay = DayList.Last(); |
63 | 64 |
string fileName = lastDay.Date.ToString(); |
64 |
string json = JsonSerializer.Serialize(lastDay); |
|
65 |
string json = JsonSerializer.Serialize(lastDay, new JsonSerializerOptions |
|
66 |
{ |
|
67 |
ReferenceHandler = ReferenceHandler.Preserve, |
|
68 |
WriteIndented = true |
|
69 |
}); |
|
65 | 70 |
AndroidFileHelper.SaveJsonToDownloads(fileName, json); |
66 | 71 |
IsBusy = false; |
67 | 72 |
#endif |
GES_PAC/ViewModel/JourneeViewModel.cs | ||
---|---|---|
1 | 1 |
using GES_PAC.Model; |
2 |
using Microsoft.EntityFrameworkCore; |
|
2 | 3 |
using System.Collections.ObjectModel; |
3 | 4 |
|
4 | 5 |
namespace GES_PAC.ViewModel |
... | ... | |
15 | 16 |
#endregion |
16 | 17 |
|
17 | 18 |
#region Constructeurs |
18 |
private JourneeViewModel() { } |
|
19 |
private JourneeViewModel() { |
|
20 |
_ = InitAsync(); |
|
21 |
} |
|
19 | 22 |
#endregion |
20 | 23 |
|
21 | 24 |
#region Méthodes |
22 |
public Journee GetCurrentDay()
|
|
25 |
public async Task InitAsync()
|
|
23 | 26 |
{ |
24 |
DateTime today = DateTime.Today; |
|
25 |
return Journees.LastOrDefault(j => j.Date.Date == today); |
|
27 |
var journees = await App.Db.Journee |
|
28 |
.Include(j => j.Calibrations) |
|
29 |
.ThenInclude(c => c.Mesures) |
|
30 |
.ThenInclude(m => m.Type) |
|
31 |
.Include(j => j.Calibrations) |
|
32 |
.ThenInclude(c => c.Phase) |
|
33 |
.Include(j => j.Series) |
|
34 |
.ThenInclude(s => s.SeriesAnimales) |
|
35 |
.ThenInclude(sa => sa.Mesures) |
|
36 |
.Include(j => j.Series) |
|
37 |
.ThenInclude(s => s.SeriesAnimales) |
|
38 |
.ThenInclude(sa => sa.Comportements) |
|
39 |
.ToListAsync(); |
|
40 |
|
|
41 |
|
|
42 |
foreach (var j in journees) |
|
43 |
{ |
|
44 |
foreach (var c in j.Calibrations) |
|
45 |
{ |
|
46 |
c.Phase = PhaseCalibration.All.FirstOrDefault(p => p.Value == c.Phase?.Value); |
|
47 |
foreach (var m in c.Mesures) |
|
48 |
{ |
|
49 |
m.Type = TypeCalibration.All.FirstOrDefault(t => t.Value == m.Type?.Value); |
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
Journees.Add(j); |
|
54 |
} |
|
26 | 55 |
} |
27 |
public PhaseCalibration GetCurrentPhase()
|
|
56 |
public Journee? GetCurrentDay()
|
|
28 | 57 |
{ |
29 |
return GetCurrentDay().GetCurrentPhase(); |
|
58 |
DateTime today = DateTime.Today; |
|
59 |
var lastDay = Journees.LastOrDefault(j => j.Date.Date == today); |
|
60 |
if (lastDay == null || lastDay.IsComplete()) |
|
61 |
return null; |
|
62 |
return lastDay; |
|
30 | 63 |
} |
31 | 64 |
public Serie? GetCurrentSet() |
32 | 65 |
{ |
GES_PAC/ViewModel/MainViewModel.cs | ||
---|---|---|
51 | 51 |
#region Constructeur |
52 | 52 |
public MainViewModel() |
53 | 53 |
{ |
54 |
//ONLY FOR TESTS |
|
55 |
var date = DateTime.Now.AddHours(-2); |
|
56 |
var newDay = new Journee(date, PersonViewModel.Instance.Persons[0], PlaceViewModel.Instance.Places[0], ""); |
|
57 |
newDay.AddSet(new Serie(date, date, 25, 25, 25)); |
|
58 |
newDay.AddCalibration(new MesureCalibration(date, 50, 40, 500, TypeCalibration.Air, ""), PhaseCalibration.DEBUT); |
|
59 |
newDay.AddCalibration(new MesureCalibration(date, 0, 0, 1000000, TypeCalibration.Methane, "dazdazd"), PhaseCalibration.DEBUT); |
|
60 |
newDay.AddCalibration(new MesureCalibration(date, 30, 30, 3000, TypeCalibration.Melange, "deqsfsdf"), PhaseCalibration.DEBUT); |
|
61 |
newDay.GetCurrentSet().AddSerieAnimal(new SerieAnimal(1, 500, date, "")); |
|
62 |
newDay.GetCurrentSet().AddMeasure(new Mesure(date, 50, 50, 50), 1, false); |
|
63 |
JourneeViewModel.Instance.Journees.Add(newDay); |
|
64 |
//ONLY FOR TESTS |
|
65 | 54 |
|
66 | 55 |
GoToCreateDayCommand = new Command(async () => await GoToCreateDayPage()); |
67 | 56 |
ResumeDayCommand = new Command(async () => await ResumeDay()); |
GES_PAC/ViewModel/PersonViewModel.cs | ||
---|---|---|
1 | 1 |
using GES_PAC.Model; |
2 |
using Microsoft.EntityFrameworkCore; |
|
2 | 3 |
using System.Collections.ObjectModel; |
3 | 4 |
|
4 | 5 |
namespace GES_PAC.ViewModel |
... | ... | |
16 | 17 |
|
17 | 18 |
#region Constructeur |
18 | 19 |
private PersonViewModel() { |
19 |
Persons.Add(new Personne("Bond", "James", "jamesbond@inrae.fr")); // Ajout d'une personne par défaut pour les tests |
|
20 |
_ = InitAsync(); |
|
21 |
} |
|
22 |
#endregion |
|
23 |
#region Méthodes |
|
24 |
public async Task InitAsync() |
|
25 |
{ |
|
26 |
var personnes = await App.Db.Personne.ToListAsync(); |
|
27 |
foreach (var p in personnes) |
|
28 |
Persons.Add(p); |
|
20 | 29 |
} |
21 | 30 |
#endregion |
22 | 31 |
} |
GES_PAC/ViewModel/PlaceViewModel.cs | ||
---|---|---|
1 | 1 |
using GES_PAC.Model; |
2 |
using Microsoft.EntityFrameworkCore; |
|
2 | 3 |
using System.Collections.ObjectModel; |
3 | 4 |
|
4 |
|
|
5 | 5 |
namespace GES_PAC.ViewModel |
6 | 6 |
{ |
7 | 7 |
public class PlaceViewModel |
... | ... | |
17 | 17 |
|
18 | 18 |
#region Constructeur |
19 | 19 |
private PlaceViewModel() { |
20 |
Places.Add(new Lieu("Elevage Langlade", "INRAE", "Mouton")); // Ajout d'un lieu par défaut pour les tests |
|
20 |
_ = InitAsync(); |
|
21 |
} |
|
22 |
#endregion |
|
23 |
#region Méthodes |
|
24 |
public async Task InitAsync() |
|
25 |
{ |
|
26 |
var lieux = await App.Db.Lieu.ToListAsync(); |
|
27 |
foreach (var l in lieux) |
|
28 |
Places.Add(l); |
|
21 | 29 |
} |
22 | 30 |
#endregion |
23 | 31 |
} |
Formats disponibles : Unified diff