-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSeed.cs
150 lines (134 loc) · 6.18 KB
/
Seed.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using api.Models;
using Microsoft.EntityFrameworkCore;
namespace api
{
public static class Seed
{
private const string alphabet = "qwertyuiopasdfghjklzxcvbnm";
private static readonly Random _rnd = new();
private static string NextString(this Random random, int len = 10) =>
Enumerable.Range(0, len)
.Select(i => alphabet[random.Next(0, alphabet.Length - 1)])
.Aggregate("", (current, next) => $"{current}{next}");
private static string NextWords(this Random random, int wordCount = 50) =>
Enumerable.Range(0, wordCount)
.Select(i => random.NextString(random.Next(0, 11)))
.Aggregate("", (current, next) => current == "" ? next : $"{current} {next}");
private static bool NextBool(this Random random) =>
random.Next(0, 2) == 1;
private static TEntity? Next<TEntity>(this IQueryable<TEntity> entities) =>
entities.OrderBy(entity => EF.Functions.Random()).FirstOrDefault();
private static List<TEntity> Pick<TEntity>(this IQueryable<TEntity> entities, int number)
{
var ret = new List<TEntity>();
while (ret.Count != number)
{
var candidate = entities.Next();
if (candidate is null || ret.Contains(candidate))
continue;
ret.Add(candidate);
}
return ret;
}
private static TEnum Next<TEnum>(this Random random)
where TEnum : Enum
{
var vals = typeof(TEnum).GetEnumValues();
return (TEnum)vals.GetValue(random.Next(0, vals.Length))!;
}
private static List<TEnum> Pick<TEnum>(this Random random, int number)
where TEnum : Enum
{
var ret = new List<TEnum>();
while (ret.Count != number)
{
var candidate = random.Next<TEnum>();
if (ret.Contains(candidate))
continue;
ret.Add(candidate);
}
return ret;
}
private static IEnumerable<TEntity> CreateFakeEntities<TEntity>(int count, Action<TEntity> fill)
where TEntity : IModel, new() =>
Enumerable.Range(1, count).Select(i =>
{
var entity = new TEntity
{
Id = i
};
fill(entity);
return entity;
});
private static async Task SeedEntityAsync<TEntity>(this DbContext db, int count, Action<TEntity> fill)
where TEntity : class, IModel, new()
{
CreateFakeEntities(count, fill).ToList().ForEach(entity =>
{
if (db.Find<TEntity>(entity.Id) is { })
return;
entity.Id = default;
db.Add(entity);
});
await db.SaveChangesAsync();
}
public static Task SeedClassesAsync(this DbContext db) =>
db.SeedEntityAsync<Class>(10, @class => @class.Name = _rnd.NextString());
public static Task SeedConditionsAsync(this DbContext db) =>
db.SeedEntityAsync<Condition>(5, condition =>
{
condition.Name = _rnd.NextString();
condition.Description = _rnd.NextWords();
});
public static Task SeedSchoolsAsync(this DbContext db) =>
db.SeedEntityAsync<School>(6, school => school.Name = _rnd.NextString());
public static Task SeedSpellTagsAsync(this DbContext db) =>
db.SeedEntityAsync<SpellTag>(20, spellTag => spellTag.Name = _rnd.NextString());
public static Task SeedSpellsAsync(this Db db) =>
db.SeedEntityAsync<Spell>(100, spell =>
{
spell.Name = _rnd.NextString();
spell.Level = _rnd.Next(0, 10);
spell.Book = _rnd.NextBool() ? _rnd.NextString() : null;
spell.School = db.Schools.Next();
spell.HasVerbalComponent = _rnd.NextBool();
spell.HasSomaticComponent = _rnd.NextBool();
spell.Materials = (!spell.HasVerbalComponent && !spell.HasSomaticComponent) || _rnd.NextBool()
? _rnd.NextWords(10)
: null;
db.SpellTags.Pick(_rnd.Next(1, 6)).ForEach(spell.SpellTags.Add);
spell.SavingThrow = _rnd.NextBool() ? _rnd.Next<SavingThrows>() : null;
spell.DamageTypes = _rnd.Pick<DamageTypes>(_rnd.Next(0, 4)).ToArray();
spell.Action = _rnd.Next<Actions>();
spell.LongerAction = _rnd.NextBool() ? _rnd.NextString() : null;
spell.Range = _rnd.NextString();
spell.Duration = _rnd.NextString();
spell.IsConcentration = _rnd.NextBool();
spell.IsRitual = _rnd.NextBool();
db.Classes.Pick(_rnd.Next(0, 6)).ForEach(spell.RestrictedClasses.Add);
spell.Description = _rnd.NextWords(250);
spell.HigherLevelDescription = _rnd.NextBool() ? _rnd.NextWords(50) : null;
spell.DamageFormula = null; // TODO: later
db.Conditions.Pick(_rnd.Next(0, 6)).ForEach(spell.RelatedConditions.Add);
spell.SpellLists = _rnd.Pick<SpellLists>(_rnd.Next(1, 4)).ToArray();
});
public static Task SeedFeatsAsync(this Db db) =>
db.SeedEntityAsync<Feat>(100, feat =>
{
feat.Name = _rnd.NextString();
feat.Level = _rnd.Next(1, 4);
feat.Level = feat.Level == 1 ? 1 : feat.Level == 2 ? 4 : 20;
feat.Description = _rnd.NextWords(100);
feat.Prerequisite = _rnd.NextBool() ? _rnd.NextString() : "";
});
public static Task SeedCharacterAsync(this Db db) =>
db.SeedEntityAsync<Character>(1, c =>
{
c.Name = "Escanor";
c.Level = 10;
c.Race = "Elf";
c.Background = "Acolyte";
c.Class = db.Classes.Next() ?? new Class();
});
}
}