SES-147 throw dialogs - player #77

Merged
s426134 merged 7 commits from SES-147 into dev 2021-01-16 21:57:59 +01:00
75 changed files with 75727 additions and 59 deletions
Showing only changes of commit 686e1b374a - Show all commits

View File

@ -35,9 +35,20 @@ namespace SessionCompanion.Database
public virtual DbSet<CharacterWeapon> CharacterWeapons { get; set; } public virtual DbSet<CharacterWeapon> CharacterWeapons { get; set; }
public virtual DbSet<OtherEquipment> OtherEquipment { get; set; } public virtual DbSet<OtherEquipment> OtherEquipment { get; set; }
public virtual DbSet<CharacterOtherEquipment> CharacterOtherEquipment { get; set; } public virtual DbSet<CharacterOtherEquipment> CharacterOtherEquipment { get; set; }
public virtual DbSet<Monster> Monsters { get; set; }
public virtual DbSet<MonsterAction> MonsterActions { get; set; }
public virtual DbSet<MonsterLegendaryAction> MonsterLegendaryActions { get; set; }
public virtual DbSet<MonsterSpecialAbility> MonsterSpecialAbilities { get; set; }
public virtual DbSet<GameAction> GameActions { get; set; }
public virtual DbSet<LegendaryAction> LegendaryActions { get; set; }
public virtual DbSet<SpecialAbility> SpecialAbilities { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
public List<SpecialAbility> SpecialAbilitiesList { get; set; }
public List<LegendaryAction> LegendaryActionsList { get; set; }
public List<GameAction> GameActionsList { get; set; }
protected IEnumerable<Weapon> SeedWeapon() protected IEnumerable<Weapon> SeedWeapon()
{ {
const string file = "../SessionCompanion.Database/JsonData/weapons.json"; const string file = "../SessionCompanion.Database/JsonData/weapons.json";
@ -98,6 +109,178 @@ namespace SessionCompanion.Database
} }
return spells; return spells;
} }
protected IEnumerable<SpecialAbility> SeedSpecialAbilities()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<SpecialAbility> specAbilities = new List<SpecialAbility>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jabilites = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jabilites)
{
if (item.special_abilities != null)
{
foreach (dynamic sp in item.special_abilities)
{
if (specAbilities.Find(x => x.Name == (string)sp.name) is null)
{
specAbilities.Add(SeedFromJsons.SingleSpecialAbilitySeeder(sp, id));
id++;
}
}
}
}
}
SpecialAbilitiesList = specAbilities;
return specAbilities;
}
protected IEnumerable<GameAction> SeedActions()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<GameAction> gameActions = new List<GameAction>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jactions = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jactions)
{
if (item.actions != null)
{
foreach (dynamic a in item.actions)
{
if (gameActions.Find(x => x.Name == (string)a.name) is null)
{
gameActions.Add(SeedFromJsons.SingleActionSeeder(a, id));
id++;
}
}
}
}
}
GameActionsList = gameActions;
return gameActions;
}
protected IEnumerable<LegendaryAction> SeedLegendaryActions()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<LegendaryAction> legendaryActions = new List<LegendaryAction>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jlegendaryactions = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jlegendaryactions)
{
if (item.legendary_actions != null)
{
foreach (dynamic la in item.legendary_actions)
{
if (legendaryActions.Find(x => x.Name == (string)la.name) is null)
{
legendaryActions.Add(SeedFromJsons.SingleLegendaryActionSeeder(la, id));
id++;
}
}
}
}
}
LegendaryActionsList = legendaryActions;
return legendaryActions;
}
protected IEnumerable<Monster> SeedMonster()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<Monster> monsters = new List<Monster>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jmonsters = JArray.Parse(json);
foreach (dynamic item in jmonsters)
monsters.Add(SeedFromJsons.SingleMonsterSeeder(item));
}
return monsters;
}
protected IEnumerable<MonsterSpecialAbility> SeedMonsterSpecialAbilities()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<MonsterSpecialAbility> monsterSpecialAbilities = new List<MonsterSpecialAbility>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jabilities = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jabilities)
{
if (item.special_abilities != null)
{
foreach (dynamic a in item.special_abilities)
{
var abilityId = SpecialAbilitiesList.Find(x => x.Name == (string)a.name).Id;
monsterSpecialAbilities.Add(new MonsterSpecialAbility { Id = id, MonsterId = (int)item.index, SpecialAbilityId = abilityId });
id++;
}
}
}
}
return monsterSpecialAbilities;
}
protected IEnumerable<MonsterAction> SeedMonsterActions()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<MonsterAction> monsterActions = new List<MonsterAction>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jactions = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jactions)
{
if (item.actions != null)
{
foreach (dynamic a in item.actions)
{
var abilityId = GameActionsList.Find(x => x.Name == (string)a.name).Id;
monsterActions.Add(new MonsterAction { Id = id, MonsterId = (int)item.index, GameActionId = abilityId });
id++;
}
}
}
}
return monsterActions;
}
protected IEnumerable<MonsterLegendaryAction> SeedMonsterLegendaryActions()
{
const string file = "../SessionCompanion.Database/JsonData/monsters.json";
List<MonsterLegendaryAction> monsterLegendaryActions = new List<MonsterLegendaryAction>();
using (StreamReader reader = new StreamReader(file))
{
var json = reader.ReadToEnd();
dynamic jactions = JArray.Parse(json);
int id = 1;
foreach (dynamic item in jactions)
{
if (item.legendary_actions != null)
{
foreach (dynamic a in item.legendary_actions)
{
var actionId = LegendaryActionsList.Find(x => x.Name == (string)a.name).Id;
monsterLegendaryActions.Add(new MonsterLegendaryAction { Id = id, MonsterId = (int)item.index, LegendaryActionId = actionId });
id++;
}
}
}
}
return monsterLegendaryActions;
}
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
@ -124,6 +307,14 @@ namespace SessionCompanion.Database
builder.Entity<Spell>().HasData(SeedSpell()); builder.Entity<Spell>().HasData(SeedSpell());
builder.Entity<CharacterSpell>().HasData(SeedData.SeedCharacterSpell()); builder.Entity<CharacterSpell>().HasData(SeedData.SeedCharacterSpell());
builder.Entity<CharacterSpellSlots>().HasData(SeedData.SeedCharacterSpellSlot()); builder.Entity<CharacterSpellSlots>().HasData(SeedData.SeedCharacterSpellSlot());
builder.Entity<Monster>().HasData(SeedMonster());
builder.Entity<SpecialAbility>().HasData(SeedSpecialAbilities());
builder.Entity<LegendaryAction>().HasData(SeedLegendaryActions());
builder.Entity<GameAction>().HasData(SeedActions());
builder.Entity<MonsterSpecialAbility>().HasData(SeedMonsterSpecialAbilities());
builder.Entity<MonsterAction>().HasData(SeedMonsterActions());
builder.Entity<MonsterLegendaryAction>().HasData(SeedMonsterLegendaryActions());
} }
} }
} }

View File

@ -0,0 +1,985 @@
[
{
"id": 1,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 4,
"Initiative": 2,
"HealthPoints": 8,
"CurrentHealthPoints": 8,
"ArmorClass": 5,
"Proficiency": 2
},
"biography": {
"Name": "Ulora",
"ClassId": 2,
"RaceId": 3,
"AlignmentId": 1,
"BackgroundId": 2,
"Sex": "Female",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 11,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 12,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 44
},
{
"SpellId": 57
}
],
"charisma": {
"Value": 5,
"Modification": -2,
"SavingThrows": 0,
"CanSavingThrows": false,
"Deception": 0,
"CanDeception": false,
"Intimidation": 0,
"CanIntimidation": false,
"Performance": 0,
"CanPerformance": false,
"Persuasion": 0,
"CanPersuasion": false
},
"constitution": {
"Value": 12,
"Modification": 2,
"SavingThrows": 2,
"CanSaveThrows": true
},
"dexterity": {
"Value": 15,
"Modification": 2,
"SavingThrows": 3,
"CanSaveThrows": true,
"Acrobatics": 3,
"CanAcrobatics": true,
"SleightOfHand": 2,
"CanSleightOfHand": true,
"Stealth": 3,
"canStealth": true
},
"intelligence": {
"Value": 14,
"Modification": 4,
"SavingThrows": 2,
"CanSaveThrows": true,
"arcana": 2,
"canArcana": true,
"History": 4,
"CanHistory": true,
"Investigation": 3,
"CanInvestigation": true,
"Nature": 1,
"CanNature": true,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 8,
"Modification": -1,
"SavingThrows": 0,
"CanSaveThrows": false,
"Athletics": 0,
"canAthletics": false
},
"wisdom": {
"Value": 10,
"Modification": 0,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 1,
"CanAnimalHandling": true,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 2,
"CanPerception": true,
"Survival": 0,
"CanSurvival": false
}
},
{
"id": 2,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 3,
"Initiative": 5,
"HealthPoints": 12,
"CurrentHealthPoints": 11,
"ArmorClass": 4,
"Proficiency": 1
},
"biography": {
"Name": "Nucate",
"ClassId": 1,
"RaceId": 1,
"AlignmentId": 2,
"BackgroundId": 1,
"Sex": "Male",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 30,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 25,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 2
},
{
"SpellId": 42
}
],
"charisma": {
"Value": 10,
"Modification": 3,
"SavingThrows": 0,
"CanSavingThrows": false,
"Deception": 0,
"CanDeception": false,
"Intimidation": 1,
"CanIntimidation": true,
"Performance": 2,
"CanPerformance": true,
"Persuasion": 0,
"CanPersuasion": false
},
"constitution": {
"Value": 11,
"Modification": 4,
"SavingThrows": 2,
"CanSaveThrows": true
},
"dexterity": {
"Value": 10,
"Modification": 1,
"SavingThrows": 4,
"CanSaveThrows": true,
"Acrobatics": 3,
"CanAcrobatics": true,
"SleightOfHand": 1,
"CanSleightOfHand": true,
"Stealth": 2,
"canStealth": true
},
"intelligence": {
"Value": 6,
"Modification": -2,
"SavingThrows": 1,
"CanSaveThrows": true,
"arcana": 1,
"canArcana": true,
"History": 4,
"CanHistory": true,
"Investigation": 0,
"CanInvestigation": false,
"Nature": 1,
"CanNature": true,
"Religion": 3,
"canReligion": true
},
"strength": {
"Value": 10,
"Modification": 1,
"SavingThrows": 0,
"CanSaveThrows": false,
"Athletics": 2,
"canAthletics": true
},
"wisdom": {
"Value": 11,
"Modification": 3,
"SavingThrows": 1,
"CanSaveThrows": true,
"AnimalHandling": 2,
"canAnimalHandling": true,
"Insight": 1,
"canInsight": true,
"medicine": 0,
"CanMedicine": false,
"Perception": 5,
"CanPerception": true,
"Survival": 2,
"CanSurvival": true
}
},
{
"id": 3,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 4,
"Initiative": 2,
"HealthPoints": 17,
"CurrentHealthPoints": 16,
"ArmorClass": 6,
"Proficiency": 3
},
"biography": {
"Name": "Muraraj",
"ClassId": 2,
"RaceId": 2,
"AlignmentId": 1,
"BackgroundId": 1,
"Sex": "Male",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 1,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 2,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
},
{
"WeaponId": 10,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 42
}
],
"charisma": {
"Value": 15,
"Modification": 2,
"SavingThrows": 2,
"CanSaveThrows": true,
"Deception": 1,
"CanDeception": true,
"Intimidation": 4,
"CanIntimidation": true,
"Performance": 2,
"CanPerformance": true,
"Persuasion": 2,
"CanPersuasion": true
},
"constitution": {
"Value": 15,
"Modification": 4,
"SavingThrows": 2,
"CanSaveThrows": true
},
"dexterity": {
"Value": 8,
"Modification": -1,
"SavingThrows": 0,
"CanSaveThrows": false,
"Acrobatics": 0,
"CanAcrobatics": false,
"SleightOfHand": 0,
"CanSleightOfHand": false,
"Stealth": 0,
"canStealth": false
},
"intelligence": {
"Value": 8,
"Modification": -1,
"SavingThrows": 0,
"CanSaveThrows": false,
"arcana": 0,
"canArcana": false,
"History": 0,
"CanHistory": false,
"Investigation": 0,
"CanInvestigation": false,
"Nature": 0,
"CanNature": false,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 18,
"Modification": 4,
"SavingThrows": 3,
"CanSaveThrows": true,
"Athletics": 5,
"canAthletics": true
},
"wisdom": {
"Value": 6,
"Modification": -3,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 0,
"CanAnimalHandling": false,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 0,
"CanPerception": false,
"Survival": 0,
"CanSurvival": false
}
},
{
"id": 4,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 8,
"Initiative": 7,
"HealthPoints": 7,
"CurrentHealthPoints": 7,
"ArmorClass": 2,
"Proficiency": 3
},
"biography": {
"Name": "Amarena",
"ClassId": 2,
"RaceId": 1,
"AlignmentId": 1,
"BackgroundId": 2,
"Sex": "Female",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 2,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 14,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
},
{
"WeaponId": 4,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 2
}
],
"charisma": {
"Value": 7,
"Modification": -2,
"SavingThrows": 0,
"CanSavingThrows": false,
"Deception": 0,
"CanDeception": false,
"Intimidation": 0,
"CanIntimidation": false,
"Performance": 0,
"CanPerformance": false,
"Persuasion": 0,
"CanPersuasion": false
},
"constitution": {
"Value": 11,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true
},
"dexterity": {
"Value": 17,
"Modification": 4,
"SavingThrows": 3,
"CanSaveThrows": true,
"Acrobatics": 4,
"CanAcrobatics": true,
"SleightOfHand": 2,
"CanSleightOfHand": true,
"Stealth": 5,
"canStealth": true
},
"intelligence": {
"Value": 10,
"Modification": 0,
"SavingThrows": 0,
"CanSaveThrows": false,
"arcana": 0,
"canArcana": false,
"History": 0,
"CanHistory": false,
"Investigation": 0,
"CanInvestigation": false,
"Nature": 0,
"CanNature": false,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 14,
"Modification": 2,
"SavingThrows": 1,
"CanSaveThrows": true,
"Athletics": 3,
"canAthletics": true
},
"wisdom": {
"Value": 7,
"Modification": 0,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 0,
"canAnimalHandling": false,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 0,
"CanPerception": false,
"Survival": 0,
"CanSurvival": false
}
},
{
"id": 5,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 2,
"Initiative": 3,
"HealthPoints": 17,
"CurrentHealthPoints": 17,
"ArmorClass": 5,
"Proficiency": 1
},
"biography": {
"Name": "Yaz' uw Emul",
"ClassId": 1,
"RaceId": 3,
"AlignmentId": 1,
"BackgroundId": 3,
"Sex": "Male",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 16,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 14,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 2
},
{
"SpellId": 65
},
{
"SpellId": 44
}
],
"charisma": {
"Value": 10,
"Modification": 0,
"SavingThrows": 0,
"CanSavingThrows": false,
"Deception": 1,
"CanDeception": true,
"Intimidation": 2,
"CanIntimidation": true,
"Performance": 0,
"CanPerformance": false,
"Persuasion": 0,
"CanPersuasion": false
},
"constitution": {
"Value": 14,
"Modification": 4,
"SavingThrows": 1,
"CanSaveThrows": true
},
"dexterity": {
"Value": 6,
"Modification": -3,
"SavingThrows": 0,
"CanSaveThrows": false,
"Acrobatics": 0,
"CanAcrobatics": false,
"SleightOfHand": 0,
"CanSleightOfHand": false,
"Stealth": 0,
"canStealth": false
},
"intelligence": {
"Value": 11,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true,
"arcana": 0,
"canArcana": false,
"History": 2,
"CanHistory": true,
"Investigation": 1,
"CanInvestigation": true,
"Nature": 0,
"CanNature": false,
"Religion": 4,
"canReligion": true
},
"strength": {
"Value": 18,
"Modification": 4,
"SavingThrows": 2,
"CanSaveThrows": true,
"Athletics": 4,
"canAthletics": true
},
"wisdom": {
"Value": 9,
"Modification": -1,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 0,
"canAnimalHandling": false,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 0,
"CanPerception": false,
"Survival": 0,
"CanSurvival": false
}
},
{
"id": 6,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 5,
"Initiative": 4,
"HealthPoints": 13,
"CurrentHealthPoints": 13,
"ArmorClass": 2,
"Proficiency": 1
},
"biography": {
"Name": "Kamul",
"ClassId": 2,
"RaceId": 1,
"AlignmentId": 2,
"BackgroundId": 1,
"Sex": "Female",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 18,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 1,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 3
},
{
"SpellId": 85
},
{
"SpellId": 94
}
],
"charisma": {
"Value": 10,
"Modification": 0,
"SavingThrows": 0,
"CanSavingThrows": false,
"Deception": 2,
"CanDeception": true,
"Intimidation": 0,
"CanIntimidation": false,
"Performance": 1,
"CanPerformance": true,
"Persuasion": 2,
"CanPersuasion": true
},
"constitution": {
"Value": 8,
"Modification": -2,
"SavingThrows": 0,
"CanSaveThrows": false
},
"dexterity": {
"Value": 12,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true,
"Acrobatics": 2,
"CanAcrobatics": true,
"SleightOfHand": 1,
"CanSleightOfHand": true,
"Stealth": 0,
"canStealth": false
},
"intelligence": {
"Value": 15,
"Modification": 4,
"SavingThrows": 2,
"CanSaveThrows": true,
"arcana": 4,
"canArcana": true,
"History": 1,
"CanHistory": true,
"Investigation": 1,
"CanInvestigation": true,
"Nature": 6,
"CanNature": true,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 13,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true,
"Athletics": 2,
"canAthletics": true
},
"wisdom": {
"Value": 13,
"Modification": 2,
"SavingThrows": 2,
"CanSaveThrows": true,
"AnimalHandling": 1,
"canAnimalHandling": true,
"Insight": 4,
"canInsight": true,
"medicine": 2,
"CanMedicine": true,
"Perception": 5,
"CanPerception": true,
"Survival": 2,
"CanSurvival": true
}
},
{
"id": 7,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 9,
"Initiative": 6,
"HealthPoints": 7,
"CurrentHealthPoints": 7,
"ArmorClass": 4,
"Proficiency": 1
},
"biography": {
"Name": "Mu",
"ClassId": 1,
"RaceId": 3,
"AlignmentId": 1,
"BackgroundId": 2,
"Sex": "Male",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 1,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 17,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
},
{
"WeaponId": 27,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 3
}
],
"charisma": {
"Value": 11,
"Modification": 1,
"SavingThrows": 1,
"CanSavingThrows": true,
"Deception": 1,
"CanDeception": true,
"Intimidation": 0,
"CanIntimidation": false,
"Performance": 0,
"CanPerformance": false,
"Persuasion": 0,
"CanPersuasion": false
},
"constitution": {
"Value": 13,
"Modification": 2,
"SavingThrows": 1,
"CanSaveThrows": true
},
"dexterity": {
"Value": 17,
"Modification": 4,
"SavingThrows": 3,
"CanSaveThrows": true,
"Acrobatics": 3,
"CanAcrobatics": true,
"SleightOfHand": 4,
"CanSleightOfHand": true,
"Stealth": 1,
"canStealth": true
},
"intelligence": {
"Value": 8,
"Modification": -2,
"SavingThrows": 0,
"CanSaveThrows": false,
"arcana": 0,
"canArcana": false,
"History": 0,
"CanHistory": false,
"Investigation": 0,
"CanInvestigation": false,
"Nature": 0,
"CanNature": false,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 18,
"Modification": 4,
"SavingThrows": 3,
"CanSaveThrows": true,
"Athletics": 5,
"canAthletics": true
},
"wisdom": {
"Value": 8,
"Modification": -2,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 0,
"canAnimalHandling": false,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 0,
"CanPerception": false,
"Survival": 0,
"CanSurvival": false
}
},
{
"id": 8,
"userId": -1,
"statistics": {
"ExperiencePoints": 0,
"Level": 1,
"Speed": 4,
"Initiative": 3,
"HealthPoints": 12,
"CurrentHealthPoints": 12,
"ArmorClass": 3,
"Proficiency": 1
},
"biography": {
"Name": "Aarak",
"ClassId": 2,
"RaceId": 3,
"AlignmentId": 1,
"BackgroundId": 2,
"Sex": "Female",
"Languages": "Common",
"background": {
"Origin": "No origin",
"History": "Nothing much"
}
},
"characterWeapons": [
{
"WeaponId": 4,
"InUse": true,
"HoldInRightHand": true,
"HoldInLeftHand": false
},
{
"WeaponId": 7,
"InUse": false,
"HoldInRightHand": false,
"HoldInLeftHand": false
}
],
"characterSpells": [
{
"SpellId": 1
},
{
"SpellId": 55
}
],
"charisma": {
"Value": 12,
"Modification": 2,
"SavingThrows": 1,
"CanSavingThrows": true,
"Deception": 0,
"CanDeception": false,
"Intimidation": 0,
"CanIntimidation": false,
"Performance": 0,
"CanPerformance": false,
"Persuasion": 3,
"CanPersuasion": true
},
"constitution": {
"Value": 11,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true
},
"dexterity": {
"Value": 15,
"Modification": 3,
"SavingThrows": 2,
"CanSaveThrows": true,
"Acrobatics": 2,
"CanAcrobatics": true,
"SleightOfHand": 1,
"CanSleightOfHand": true,
"Stealth": 4,
"canStealth": true
},
"intelligence": {
"Value": 12,
"Modification": 1,
"SavingThrows": 1,
"CanSaveThrows": true,
"arcana": 0,
"canArcana": false,
"History": 0,
"CanHistory": false,
"Investigation": 0,
"CanInvestigation": false,
"Nature": 2,
"CanNature": true,
"Religion": 0,
"canReligion": false
},
"strength": {
"Value": 15,
"Modification": 4,
"SavingThrows": 3,
"CanSaveThrows": true,
"Athletics": 2,
"canAthletics": true
},
"wisdom": {
"Value": 6,
"Modification": -4,
"SavingThrows": 0,
"CanSaveThrows": false,
"AnimalHandling": 0,
"canAnimalHandling": false,
"Insight": 0,
"canInsight": false,
"medicine": 0,
"CanMedicine": false,
"Perception": 0,
"CanPerception": false,
"Survival": 0,
"CanSurvival": false
}
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class GameActionRepository : Repository<GameAction>, IRepository<GameAction>
{
public GameActionRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class LegendaryActionRepository : Repository<LegendaryAction>, IRepository<LegendaryAction>
{
public LegendaryActionRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class MonsterActionsRepository : Repository<MonsterAction>, IRepository<MonsterAction>
{
public MonsterActionsRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class MonsterLegendaryActionsRepository : Repository<MonsterLegendaryAction>, IRepository<MonsterLegendaryAction>
{
public MonsterLegendaryActionsRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class MonsterRepository : Repository<Monster>, IRepository<Monster>
{
public MonsterRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class MonsterSpecialAbilitiesRepository : Repository<MonsterSpecialAbility>, IRepository<MonsterSpecialAbility>
{
public MonsterSpecialAbilitiesRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Database.Repositories
{
public class SpecialAbilityRepository : Repository<SpecialAbility>, IRepository<SpecialAbility>
{
public SpecialAbilityRepository(ApplicationDbContext _dbContext) : base(_dbContext)
{ }
}
}

View File

@ -320,5 +320,138 @@ namespace SessionCompanion.Database
return spell; return spell;
} }
static public SpecialAbility SingleSpecialAbilitySeeder(dynamic item, int id)
{
SpecialAbility monsterSpecialAbility = new SpecialAbility();
monsterSpecialAbility.Id = id;
monsterSpecialAbility.Name = item.name;
if (item.damage_dice != null)
{
var dice = SplitDice((string)item.damage_dice);
monsterSpecialAbility.DamageDiceAmount = dice.Item1;
monsterSpecialAbility.DamageDice = dice.Item2;
}
monsterSpecialAbility.Description = item.desc;
return monsterSpecialAbility;
}
static public GameAction SingleActionSeeder(dynamic item, int id)
{
GameAction monsterAction = new GameAction();
monsterAction.Id = id;
monsterAction.Name = item.name;
monsterAction.AttackBonus = item.attack_bonus;
monsterAction.DamageBonus = item.damage_bonus;
if (item.damage_dice != null)
{
var dice = SplitDice((string)item.damage_dice);
monsterAction.DamageDiceAmount = dice.Item1;
monsterAction.DamageDice = dice.Item2;
}
monsterAction.Description = item.desc;
return monsterAction;
}
static public LegendaryAction SingleLegendaryActionSeeder(dynamic item, int id)
{
LegendaryAction monsterLegendaryAction = new LegendaryAction();
monsterLegendaryAction.Id = id;
monsterLegendaryAction.Name = item.name;
monsterLegendaryAction.Description = item.desc;
return monsterLegendaryAction;
}
static public Monster SingleMonsterSeeder(dynamic item)
{
Monster monster = new Monster();
monster.Id = item.index;
monster.Name = item.name;
monster.Size = item.size;
monster.Type = item.type;
monster.Subtype = item.subtype;
monster.Alignment = item.alignment;
monster.ArmorClass = item.armor_class;
monster.HitPoints = item.hit_points;
var dice = SplitDice((string)item.hit_dice);
monster.HitDiceAmount = dice.Item1;
monster.HitDiceType = dice.Item2;
monster.WalkSpeed = item.speed.walk;
monster.FlySpeed = item.speed.fly;
monster.SwimSpeed = item.speed.swim;
monster.Strength = item.strength;
monster.StrengthSave = item.strength_save;
monster.Dexterity = item.dexterity;
monster.DexteritySave = item.dexterity_save;
monster.Constitution = item.constitution;
monster.ConstitutionSave = item.constitution_save;
monster.Wisdom = item.wisdom;
monster.WisdomSave = item.wisdom_save;
monster.Charisma = item.charisma;
monster.CharismaSave = item.charsisma_save;
monster.Intelligence = item.intelligence;
monster.IntelligenceSave = item.intelligence_save;
foreach (dynamic dv in item.damage_vulnerabilities)
monster.MonsterDamageVulnerabilities += dv + ";";
if (monster.MonsterDamageVulnerabilities != null)
monster.MonsterDamageVulnerabilities = monster.MonsterDamageVulnerabilities.Remove(monster.MonsterDamageVulnerabilities.Length - 1);
foreach (dynamic dr in item.damage_resistances)
monster.MonsterDamageResistances += dr + ";";
if (monster.MonsterDamageResistances != null)
monster.MonsterDamageResistances = monster.MonsterDamageResistances.Remove(monster.MonsterDamageResistances.Length - 1);
foreach (dynamic di in item.damage_immunities)
monster.MonsterDamageImmunities += di + ";";
if (monster.MonsterDamageImmunities != null)
monster.MonsterDamageImmunities = monster.MonsterDamageImmunities.Remove(monster.MonsterDamageImmunities.Length - 1);
foreach (dynamic ci in item.condition_immunities)
monster.MonsterConditionImmunities += ci + ";";
if (monster.MonsterConditionImmunities != null)
monster.MonsterConditionImmunities = monster.MonsterConditionImmunities.Remove(monster.MonsterConditionImmunities.Length - 1);
monster.MonsterSenses = item.senses;
monster.MonsterLanguages = item.languages;
monster.ChallengeRating = item.challenge_rating;
return monster;
}
static public Tuple<int, int> SplitDice(string dice)
{
int stop = dice.IndexOf('d');
var amount = int.Parse(dice.Substring(0, stop));
stop++;
var value = int.Parse(dice.Substring(stop, dice.Length - stop));
return new Tuple<int, int>(amount, value);
}
} }
} }

View File

@ -21,8 +21,4 @@
<ProjectReference Include="..\SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj" /> <ProjectReference Include="..\SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="JsonData\" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class GameAction : BaseEntity
{
// <summary>
/// Nazwa akcji
/// </summary>
public string Name { get; set; }
/// <summary>
/// Opis akcji
/// </summary>
public string Description { get; set; }
public int AttackBonus { get; set; }
public int? DamageDice { get; set; }
public int? DamageDiceAmount { get; set; }
public int? DamageBonus { get; set; }
public virtual ICollection<MonsterAction> MonsterActions { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class LegendaryAction : BaseEntity
{
// <summary>
/// Nazwa legendarnej akcji
/// </summary>
public string Name { get; set; }
/// <summary>
/// Opis akcji
/// </summary>
public string Description { get; set; }
public virtual ICollection<MonsterLegendaryAction> MonsterLegendaryActions { get; set; }
}
}

View File

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class Monster : BaseEntity
{
/// <summary>
/// Nazwa potwora
/// </summary>
public string Name { get; set; }
/// <summary>
/// Rozmiar potwora
/// </summary>
public string Size { get; set; }
/// <summary>
/// Rodzaj potwora
/// </summary>
public string Type { get; set; }
/// <summary>
/// Podtyp potwora
/// </summary>
public string Subtype { get; set; }
/// <summary>
/// Charakter potwora
/// </summary>
public string Alignment { get; set; }
/// <summary>
/// Poziom pancerza potwora
/// </summary>
public int ArmorClass { get; set; }
/// <summary>
/// Iloś punktów zycia potwora
/// </summary>
public int HitPoints { get; set; }
/// <summary>
/// Ilość kości określajacych punkty życia potwora
/// </summary>
public int HitDiceAmount { get; set; }
/// <summary>
/// Kość którą rzucamy aby określić punkty życia potwora
/// </summary>
public int HitDiceType { get; set; }
/// <summary>
/// Szybkość chodzenia potwora
/// </summary>
public string WalkSpeed { get; set; }
/// <summary>
/// Szybkość pływania potwora
/// </summary>
public string SwimSpeed { get; set; }
/// <summary>
/// Szybkość latania potwora
/// </summary>
public string FlySpeed { get; set; }
/// <summary>
/// Punkty zręczności potwora
/// </summary>
public int Dexterity { get; set; }
public int? DexteritySave { get; set; }
/// <summary>
/// Punkty siły potwora
/// </summary>
public int Strength { get; set; }
public int? StrengthSave { get; set; }
/// <summary>
/// Punkty kondycji potwora
/// </summary>
public int Constitution { get; set; }
public int? ConstitutionSave { get; set; }
/// <summary>
/// Punkty inteligencji potwora
/// </summary>
public int Intelligence { get; set; }
public int? IntelligenceSave { get; set; }
/// <summary>
/// Punkty mądrości potwora
/// </summary>
public int Wisdom { get; set; }
public int? WisdomSave { get; set; }
/// <summary>
/// Punkty charyzmy potwora
/// </summary>
public int Charisma { get; set; }
public int? CharismaSave { get; set; }
/// <summary>
/// Poziom trudności potwora
/// </summary>
public int ChallengeRating { get; set; }
/// <summary>
/// Punkty doświadczenia za zabicie potwora
/// </summary>
public int ExperiencePoints { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterActions
/// </summary>
public virtual ICollection<MonsterAction> MonsterAction { get; set; }
/// <summary>
/// Na jakie stany odporny jest potwor
/// </summary>
public string MonsterConditionImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia odporny jest potwor
/// </summary>
public string MonsterDamageImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia potwor ma zmniejszoną słabosc
/// </summary>
public string MonsterDamageResistances { get; set; }
/// <summary>
/// Na co potwor jest wrazliwy
/// </summary>
public string MonsterDamageVulnerabilities { get; set; }
/// <summary>
/// Jezyki jakimi wlada potwor
/// </summary>
public string MonsterLanguages { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterLegendaryActions
/// </summary>
public virtual ICollection<MonsterLegendaryAction> MonsterLegendaryAction { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterSenses
/// </summary>
public string MonsterSenses { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterSpecialAbilities
/// </summary>
public virtual ICollection<MonsterSpecialAbility> MonsterSpecialAbility { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class MonsterAction : BaseEntity
{
/// <summary>
/// Id potwora
/// </summary>
public int MonsterId { get; set; }
/// <summary>
/// Połączenie z tabelą Monsters
/// </summary>
public virtual Monster Monster { get; set; }
public int GameActionId { get; set; }
public virtual GameAction GameAction { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class MonsterLegendaryAction : BaseEntity
{
/// <summary>
/// Id potwora
/// </summary>
public int MonsterId { get; set; }
public int LegendaryActionId { get; set; }
/// <summary>
/// Połączenie z tabelą Monster
/// </summary>
public virtual Monster Monster { get; set; }
public virtual LegendaryAction LegendaryActions { get; set; }
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class MonsterSpecialAbility : BaseEntity
{
public int SpecialAbilityId { get; set; }
public int? DamageDice { get; set; }
public int? DamageDiceAmount { get; set; }
/// <summary>
/// Id potwora
/// </summary>
public int? MonsterId { get; set; }
public virtual SpecialAbility SpecialAbility { get; set; }
/// <summary>
/// Połączenie z tabelą Monster
/// </summary>
public virtual Monster Monster { get; set; }
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.Database.Tables
{
public class SpecialAbility : BaseEntity
{
// <summary>
/// Nazwa umiejętności
/// </summary>
public string Name { get; set; }
/// <summary>
/// Opis umiejętności
/// </summary>
public string Description { get; set; }
public int? DamageDice { get; set; }
public int? DamageDiceAmount { get; set; }
public virtual ICollection<MonsterSpecialAbility> MonsterSpecialAbilities { get; set; }
}
}

View File

@ -7,10 +7,14 @@ namespace SessionCompanion.Services.Interfaces
using System.Threading.Tasks; using System.Threading.Tasks;
using SessionCompanion.Database.Tables; using SessionCompanion.Database.Tables;
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.Services.Base; using SessionCompanion.Services.Base;
using SessionCompanion.ViewModels.ApiResponses;
using SessionCompanion.ViewModels.CharacterArmorViewModels; using SessionCompanion.ViewModels.CharacterArmorViewModels;
public interface ICharacterArmorService : IServiceBase<CharacterArmorViewModel, CharacterArmor> public interface ICharacterArmorService : IServiceBase<CharacterArmorViewModel, CharacterArmor>
{ {
Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterArmor(int characterId, int newArmorId);
Task<List<CharacterArmorViewModelDetails>> GetCharacterArmorsTaskList(int characterId);
} }
} }

View File

@ -12,5 +12,6 @@ namespace SessionCompanion.Services.Interfaces
public interface ICharacterOtherEquipmentService : IServiceBase<CharacterOtherEquipmentViewModel, CharacterOtherEquipment> public interface ICharacterOtherEquipmentService : IServiceBase<CharacterOtherEquipmentViewModel, CharacterOtherEquipment>
{ {
Task<List<CharacterOtherEquipmentWithDetailsViewModel>> GetCharacterOtherEquipmentList(int characterId);
} }
} }

View File

@ -1,6 +1,8 @@
using SessionCompanion.Database.Tables; using SessionCompanion.Database.Tables;
using SessionCompanion.Services.Base; using SessionCompanion.Services.Base;
using SessionCompanion.ViewModels.CharacterViewModels; using SessionCompanion.ViewModels.CharacterViewModels;
using SessionCompanion.ViewModels.ClassViewModels;
using SessionCompanion.ViewModels.RaceViewModels;
using SessionCompanion.ViewModels.UniversalModels; using SessionCompanion.ViewModels.UniversalModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,5 +17,7 @@ namespace SessionCompanion.Services.Interfaces
Task<IEnumerable<CharacterForLoginViewModel>> GetUserLoginCharacters(int userId); Task<IEnumerable<CharacterForLoginViewModel>> GetUserLoginCharacters(int userId);
Task<List<UniversalStatisticViewModel>> GetCharacterStatistics(int characterId); Task<List<UniversalStatisticViewModel>> GetCharacterStatistics(int characterId);
Task<CharacterBasicInfoViewModel> GetBasicCharacterbasicInfo(int characterId); Task<CharacterBasicInfoViewModel> GetBasicCharacterbasicInfo(int characterId);
Task<IEnumerable<CharacterFromTemplatesSimpleViewModel>> GetCharactersFromTemplate(List<RaceViewModel> raceViewModels, List<ClassViewModel> classViewModels);
Task CreateCharactersFromTemplate(int characterId, int userId, string newName);
} }
} }

View File

@ -4,7 +4,14 @@ using SessionCompanion.ViewModels.CharacterWeaponViewModels;
namespace SessionCompanion.Services.Interfaces namespace SessionCompanion.Services.Interfaces
{ {
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.ViewModels.ApiResponses;
using System.Collections.Generic;
using System.Threading.Tasks;
public interface ICharacterWeaponService : IServiceBase<CharacterWeaponViewModel, CharacterWeapon> public interface ICharacterWeaponService : IServiceBase<CharacterWeaponViewModel, CharacterWeapon>
{ {
Task<List<CharacterWeaponWithWeaponDetailsViewModel>> GetCharacterWeaponsList(int characterId);
Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterWeapon(CharacterWeaponViewModel model);
} }
} }

View File

@ -0,0 +1,14 @@
using SessionCompanion.Database.Tables;
using SessionCompanion.Services.Base;
namespace SessionCompanion.Services.Interfaces
{
using System.Collections.Generic;
using SessionCompanion.ViewModels.MonsterViewModels;
public interface IMonsterService : IServiceBase<MonsterViewModel, Monster>
{
List<MonsterViewModel> GetAllMonstersList();
}
}

View File

@ -0,0 +1,15 @@
using AutoMapper;
using SessionCompanion.Database.Tables;
namespace SessionCompanion.Services.Profiles
{
using SessionCompanion.ViewModels.MonsterViewModels;
public class MonsterProfile : Profile
{
public MonsterProfile()
{
CreateMap<MonsterViewModel, Monster>().ReverseMap();
}
}
}

View File

@ -15,11 +15,74 @@ namespace SessionCompanion.Services.Services
using SessionCompanion.Database.Tables; using SessionCompanion.Database.Tables;
using SessionCompanion.Services.Base; using SessionCompanion.Services.Base;
using SessionCompanion.Services.Interfaces; using SessionCompanion.Services.Interfaces;
using SessionCompanion.ViewModels.ApiResponses;
using SessionCompanion.ViewModels.CharacterArmorViewModels; using SessionCompanion.ViewModels.CharacterArmorViewModels;
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.ViewModels.CharacterOtherEquipmentViewModels;
public class CharacterArmorService : ServiceBase<CharacterArmorViewModel, CharacterArmor>, ICharacterArmorService public class CharacterArmorService : ServiceBase<CharacterArmorViewModel, CharacterArmor>, ICharacterArmorService
{ {
public CharacterArmorService(IMapper mapper, IRepository<CharacterArmor> repository) : base(mapper, repository) public CharacterArmorService(IMapper mapper, IRepository<CharacterArmor> repository) : base(mapper, repository)
{ } { }
public async Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterArmor(int characterId, int newArmorId)
{
CharacterArmor armorInUse = new CharacterArmor();
CharacterArmor armorToUse = new CharacterArmor();
try
{
armorInUse = await Repository.Get(c => c.CharacterId.Equals(characterId))
.Include(a => a.Armor).Where(x => x.InUse == true).SingleAsync();
armorToUse = await Repository.Get(c => c.ArmorId.Equals(newArmorId) && c.CharacterId.Equals(characterId)).SingleAsync();
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
if (armorToUse is null)
return new ErrorResponse() { StatusCode = 204, Message = "No armor to change to" };
if (armorInUse is null)
{
armorToUse.InUse = true;
try
{
await Repository.Update(armorToUse);
await Repository.Save();
return new SuccessResponse("Character armor updated") { SuccessCode = 200 };
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
}
armorInUse.InUse = false;
armorToUse.InUse = true;
try
{
await Repository.Update(armorInUse);
await Repository.Update(armorToUse);
await Repository.Save();
return new SuccessResponse("Character armor updated") { SuccessCode = 204 };
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
}
/// <summary>
/// Metoda pobiera listę pancerzy konkretnej postaci
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista pancerzy posiadanych przez postać </returns>
public async Task<List<CharacterArmorViewModelDetails>> GetCharacterArmorsTaskList(int characterId)
{
var characterWeapons = await Repository.Get().Where(a => a.CharacterId.Equals(characterId)).Include(a => a.Armor).ToListAsync();
var result = Mapper.Map<List<CharacterArmorViewModelDetails>>(characterWeapons);
return result;
}
} }
} }

View File

@ -1,7 +1,11 @@
namespace SessionCompanion.Services.Services namespace SessionCompanion.Services.Services
{ {
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper; using AutoMapper;
using Microsoft.EntityFrameworkCore;
using SessionCompanion.Database.Repositories.Base; using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables; using SessionCompanion.Database.Tables;
using SessionCompanion.Services.Base; using SessionCompanion.Services.Base;
@ -13,5 +17,17 @@
public CharacterOtherEquipmentService(IMapper mapper, IRepository<CharacterOtherEquipment> repository) : base(mapper, repository) public CharacterOtherEquipmentService(IMapper mapper, IRepository<CharacterOtherEquipment> repository) : base(mapper, repository)
{ } { }
/// <summary>
/// Metoda pobiera listę pozostałego ekwipunku konkretnej postaci
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista pozostałego ekwpinuku posiadanego przez postać </returns>
public async Task<List<CharacterOtherEquipmentWithDetailsViewModel>> GetCharacterOtherEquipmentList(int characterId)
{
var characterWeapons = await Repository.Get().Where(a => a.CharacterId.Equals(characterId)).Include(a => a.OtherEquipment).ToListAsync();
var result = Mapper.Map<List<CharacterOtherEquipmentWithDetailsViewModel>>(characterWeapons);
return result;
}
} }
} }

View File

@ -16,12 +16,14 @@ using System.IO;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using SessionCompanion.ViewModels.UniversalModels; using SessionCompanion.ViewModels.UniversalModels;
using SessionCompanion.Services.Helpers; using SessionCompanion.Services.Helpers;
using SessionCompanion.ViewModels.RaceViewModels;
using SessionCompanion.ViewModels.ClassViewModels;
namespace SessionCompanion.Services.Services namespace SessionCompanion.Services.Services
{ {
public class CharacterService : ServiceBase<CharacterViewModel, Character>, ICharacterService public class CharacterService : ServiceBase<CharacterViewModel, Character>, ICharacterService
{ {
public CharacterService(IMapper mapper, IRepository<Character> repository) : base(mapper, repository) public CharacterService(IMapper mapper, IRepository<Character> repository, IRepository<Class> classRepository) : base(mapper, repository)
{ } { }
/// <summary> /// <summary>
@ -111,5 +113,57 @@ namespace SessionCompanion.Services.Services
var result = Mapper.Map<CharacterBasicInfoViewModel>(character); var result = Mapper.Map<CharacterBasicInfoViewModel>(character);
return result; return result;
} }
/// <summary>
/// Function returns basic stats from Characters in templates
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<CharacterFromTemplatesSimpleViewModel>> GetCharactersFromTemplate(List<RaceViewModel> raceViewModels, List<ClassViewModel> classViewModels)
{
const string file = "../SessionCompanion.Database/JsonData/characters_templates.json";
List<CharacterFromTemplatesSimpleViewModel> basicStats = new List<CharacterFromTemplatesSimpleViewModel>();
using (StreamReader reader = new StreamReader(file))
{
var json = await reader.ReadToEndAsync();
foreach (var item in JArray.Parse(json))
{
CharacterFromTemplatesSimpleViewModel characterFromTemplatesSimpleViewModel = new CharacterFromTemplatesSimpleViewModel()
{
Id = (int)item["id"],
Class = classViewModels.Where(c => c.Id.Equals((int)item["biography"]["ClassId"])).Select(c => c.Name).Single(),
Race = raceViewModels.Where(r => r.Id.Equals((int)item["biography"]["RaceId"])).Select(r => r.Name).Single(),
Name = (string)item["biography"]["Name"]
};
basicStats.Add(characterFromTemplatesSimpleViewModel);
}
}
return basicStats;
}
/// <summary>
/// Function creates chosen template Character for given User, it can also change its name
/// </summary>
/// <param name="characterId"></param>
/// <param name="userId"></param>
/// <param name="newName"></param>
/// <returns></returns>
public async Task CreateCharactersFromTemplate(int characterId, int userId, string newName)
{
const string file = "../SessionCompanion.Database/JsonData/characters_templates.json";
List<Character> characters = new List<Character>();
using (StreamReader reader = new StreamReader(file))
{
var json = await reader.ReadToEndAsync();
characters = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Character>>(json);
}
var character = characters.Where(x => x.Id.Equals(characterId)).Single();
character.Id = 0;
character.UserId = userId;
if (newName != null)
character.Biography.Name = newName;
await Repository.Create(character);
await Repository.Save();
}
} }
} }

View File

@ -7,9 +7,88 @@ using SessionCompanion.ViewModels.CharacterWeaponViewModels;
namespace SessionCompanion.Services.Services namespace SessionCompanion.Services.Services
{ {
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.ViewModels.ApiResponses;
public class CharacterWeaponService : ServiceBase<CharacterWeaponViewModel, CharacterWeapon>, ICharacterWeaponService public class CharacterWeaponService : ServiceBase<CharacterWeaponViewModel, CharacterWeapon>, ICharacterWeaponService
{ {
public CharacterWeaponService(IMapper mapper, IRepository<CharacterWeapon> repository) : base(mapper, repository) public CharacterWeaponService(IMapper mapper, IRepository<CharacterWeapon> repository) : base(mapper, repository)
{ } { }
/// <summary>
/// Metoda pobiera listę broni konkretnej postaci
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista broni posiadanych przez postać </returns>
public async Task<List<CharacterWeaponWithWeaponDetailsViewModel>> GetCharacterWeaponsList(int characterId)
{
var characterWeapons = await Repository.Get().Where(w => w.CharacterId.Equals(characterId)).Include(w => w.Weapon).ToListAsync();
var result = Mapper.Map<List<CharacterWeaponWithWeaponDetailsViewModel>>(characterWeapons);
return result;
}
public async Task<Either<SuccessResponse,ErrorResponse>> ChangeCharacterWeapon(CharacterWeaponViewModel model)
{
// Dodaj optional rozbro postac
var allWeapons = await Repository.Get(c => c.CharacterId.Equals(model.CharacterId)).AsNoTracking().ToListAsync();
var weaponsInUse = allWeapons.Where(w => w.InUse.Equals(true)).ToList();
var weapon = Mapper.Map<CharacterWeapon>(model);
weapon.Id = allWeapons.Where(w => w.WeaponId.Equals(model.WeaponId)).Select(x => x.Id).FirstOrDefault();
if (weaponsInUse.Count() == 0)
{
// no weapon in use
// just use new one
await Repository.Update(weapon);
await Repository.Save();
return new SuccessResponse("Weapon changed") { SuccessCode = 200 };
}
var weaponInBothHands = weaponsInUse.Where(w => w.HoldInLeftHand.Equals(true) && w.HoldInRightHand.Equals(true));
if ((model.HoldInLeftHand && model.HoldInRightHand) || (weaponInBothHands.Count() > 0))
{
// our model weapon uses both hands
// or there is weapon already in both hands
foreach (var w in weaponsInUse)
{
w.InUse = false;
w.HoldInLeftHand = false;
w.HoldInRightHand = false;
await Repository.Update(w);
}
await Repository.Update(weapon);
await Repository.Save();
return new SuccessResponse("Weapon changed") { SuccessCode = 200 };
}
var weaponsToChange = weaponsInUse.Where(w => w.HoldInLeftHand.Equals(model.HoldInLeftHand) && w.HoldInRightHand.Equals(model.HoldInRightHand));
if (weaponsToChange.Count() == 1)
{
// there is weapon in the same hand set as our
// we update it
var weaponToChange = weaponsToChange.Single();
weaponToChange.InUse = false;
weaponToChange.HoldInLeftHand = false;
weaponToChange.HoldInRightHand = false;
await Repository.Update(weaponToChange);
await Repository.Update(weapon);
await Repository.Save();
return new SuccessResponse("Weapon changed") { SuccessCode = 200 };
}
// weapon is armed in empty hand
await Repository.Update(weapon);
await Repository.Save();
return new SuccessResponse("Weapon changed") { SuccessCode = 200 };
}
} }
} }

View File

@ -0,0 +1,29 @@
using AutoMapper;
using SessionCompanion.Database.Repositories.Base;
using SessionCompanion.Database.Tables;
using SessionCompanion.Services.Base;
using SessionCompanion.Services.Interfaces;
using SessionCompanion.ViewModels.IntelligenceViewModels;
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.Services.Services
{
using System.Threading.Tasks;
using SessionCompanion.ViewModels.MonsterViewModels;
public class MonsterService : ServiceBase<MonsterViewModel, Monster>, IMonsterService
{
public MonsterService(IMapper mapper, IRepository<Monster> repository) : base(mapper, repository)
{ }
public List<MonsterViewModel> GetAllMonstersList()
{
var monsters = this.Repository.Get();
return this.Mapper.Map<List<MonsterViewModel>>(monsters);
}
}
}

View File

@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SessionCompanion.Database\SessionCompanion.Database.csproj" /> <ProjectReference Include="..\SessionCompanion.Database\SessionCompanion.Database.csproj" />
<ProjectReference Include="..\SessionCompanion.Extensions\SessionCompanion.Extensions.csproj" />
<ProjectReference Include="..\SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj" /> <ProjectReference Include="..\SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SessionCompanion.ViewModels.CharacterViewModels
{
public class CharacterFromTemplatesSimpleViewModel
{
/// <summary>
/// Id postaci
/// </summary>
public int Id { get; set; }
/// <summary>
/// Imie postaci
/// </summary>
public string Name { get; set; }
/// <summary>
/// Nazwa rasy postaci
/// </summary>
public string Race { get; set; }
/// <summary>
/// Nazwa Klasy postaci
/// </summary>
public string Class { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.GameActionViewModels
{
public class GameActionViewModel
{
public int Id { get; set; }
public string Name { get; set; }
/// <summary>
/// Opis akcji
/// </summary>
public string Description { get; set; }
public int AttackBonus { get; set; }
public int? DamageDice { get; set; }
public int? DamageDiceAmount { get; set; }
public int? DamageBonus { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.LegendaryActionViewModels
{
public class LegendaryActionViewModel
{
public int Id { get; set; }
// <summary>
/// Nazwa legendarnej akcji
/// </summary>
public string Name { get; set; }
/// <summary>
/// Opis akcji
/// </summary>
public string Description { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.MonsterActionsViewModels
{
public class MonsterActionsViewModel
{
public int Id { get; set; }
/// <summary>
/// Id potwora
/// </summary>
public int MonsterId { get; set; }
public int GameActionId { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.MonsterLegendaryActionsViewModels
{
public class MonsterLegendaryActionsViewModel
{
public int Id { get; set; }
public int MonsterId { get; set; }
public int LegendaryActionId { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.MonsterSpecialAbilitiesViewModels
{
public class MonsterSpecialAbilitiesViewModel
{
public int Id { get; set; }
public int MonsterId { get; set; }
public int LegendaryActionId { get; set; }
}
}

View File

@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.MonsterViewModels
{
using SessionCompanion.ViewModels.GameActionViewModels;
using SessionCompanion.ViewModels.LegendaryActionViewModels;
using SessionCompanion.ViewModels.SpecialAbilityViewModels;
public class MonsterAllInformationViewModel
{
public int Id { get; set; }
/// <summary>
/// Nazwa potwora
/// </summary>
public string Name { get; set; }
/// <summary>
/// Rozmiar potwora
/// </summary>
public string Size { get; set; }
/// <summary>
/// Rodzaj potwora
/// </summary>
public string Type { get; set; }
/// <summary>
/// Podtyp potwora
/// </summary>
public string Subtype { get; set; }
/// <summary>
/// Charakter potwora
/// </summary>
public string Alignment { get; set; }
/// <summary>
/// Poziom pancerza potwora
/// </summary>
public int ArmorClass { get; set; }
/// <summary>
/// Iloś punktów zycia potwora
/// </summary>
public int HitPoints { get; set; }
/// <summary>
/// Ilość kości określajacych punkty życia potwora
/// </summary>
public int HitDiceAmount { get; set; }
/// <summary>
/// Kość którą rzucamy aby określić punkty życia potwora
/// </summary>
public int HitDiceType { get; set; }
/// <summary>
/// Szybkość chodzenia potwora
/// </summary>
public string WalkSpeed { get; set; }
/// <summary>
/// Szybkość pływania potwora
/// </summary>
public string SwimSpeed { get; set; }
/// <summary>
/// Szybkość latania potwora
/// </summary>
public string FlySpeed { get; set; }
/// <summary>
/// Punkty zręczności potwora
/// </summary>
public int Dexterity { get; set; }
public int? DexteritySave { get; set; }
/// <summary>
/// Punkty siły potwora
/// </summary>
public int Strength { get; set; }
public int? StrengthSave { get; set; }
/// <summary>
/// Punkty kondycji potwora
/// </summary>
public int Constitution { get; set; }
public int? ConstitutionSave { get; set; }
/// <summary>
/// Punkty inteligencji potwora
/// </summary>
public int Intelligence { get; set; }
public int? IntelligenceSave { get; set; }
/// <summary>
/// Punkty mądrości potwora
/// </summary>
public int Wisdom { get; set; }
public int? WisdomSave { get; set; }
/// <summary>
/// Punkty charyzmy potwora
/// </summary>
public int Charisma { get; set; }
public int? CharismaSave { get; set; }
/// <summary>
/// Poziom trudności potwora
/// </summary>
public int ChallengeRating { get; set; }
/// <summary>
/// Punkty doświadczenia za zabicie potwora
/// </summary>
public int ExperiencePoints { get; set; }
/// <summary>
/// Na jakie stany odporny jest potwor
/// </summary>
public string MonsterConditionImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia odporny jest potwor
/// </summary>
public string MonsterDamageImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia potwor ma zmniejszoną słabosc
/// </summary>
public string MonsterDamageResistances { get; set; }
/// <summary>
/// Na co potwor jest wrazliwy
/// </summary>
public string MonsterDamageVulnerabilities { get; set; }
/// <summary>
/// Jezyki jakimi wlada potwor
/// </summary>
public string MonsterLanguages { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterSenses
/// </summary>
public string MonsterSenses { get; set; }
public ICollection<GameActionViewModel> MonsterGameActions { get; set; }
public ICollection<LegendaryActionViewModel> MonsteLegendaryActions { get; set; }
public ICollection<SpecialAbilityViewModel> MonsterSpecialAbilities { get; set; }
}
}

View File

@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.MonsterViewModels
{
public class MonsterViewModel
{
public int Id { get; set; }
/// <summary>
/// Nazwa potwora
/// </summary>
public string Name { get; set; }
/// <summary>
/// Rozmiar potwora
/// </summary>
public string Size { get; set; }
/// <summary>
/// Rodzaj potwora
/// </summary>
public string Type { get; set; }
/// <summary>
/// Podtyp potwora
/// </summary>
public string Subtype { get; set; }
/// <summary>
/// Charakter potwora
/// </summary>
public string Alignment { get; set; }
/// <summary>
/// Poziom pancerza potwora
/// </summary>
public int ArmorClass { get; set; }
/// <summary>
/// Iloś punktów zycia potwora
/// </summary>
public int HitPoints { get; set; }
/// <summary>
/// Ilość kości określajacych punkty życia potwora
/// </summary>
public int HitDiceAmount { get; set; }
/// <summary>
/// Kość którą rzucamy aby określić punkty życia potwora
/// </summary>
public int HitDiceType { get; set; }
/// <summary>
/// Szybkość chodzenia potwora
/// </summary>
public string WalkSpeed { get; set; }
/// <summary>
/// Szybkość pływania potwora
/// </summary>
public string SwimSpeed { get; set; }
/// <summary>
/// Szybkość latania potwora
/// </summary>
public string FlySpeed { get; set; }
/// <summary>
/// Punkty zręczności potwora
/// </summary>
public int Dexterity { get; set; }
public int? DexteritySave { get; set; }
/// <summary>
/// Punkty siły potwora
/// </summary>
public int Strength { get; set; }
public int? StrengthSave { get; set; }
/// <summary>
/// Punkty kondycji potwora
/// </summary>
public int Constitution { get; set; }
public int? ConstitutionSave { get; set; }
/// <summary>
/// Punkty inteligencji potwora
/// </summary>
public int Intelligence { get; set; }
public int? IntelligenceSave { get; set; }
/// <summary>
/// Punkty mądrości potwora
/// </summary>
public int Wisdom { get; set; }
public int? WisdomSave { get; set; }
/// <summary>
/// Punkty charyzmy potwora
/// </summary>
public int Charisma { get; set; }
public int? CharismaSave { get; set; }
/// <summary>
/// Poziom trudności potwora
/// </summary>
public int ChallengeRating { get; set; }
/// <summary>
/// Punkty doświadczenia za zabicie potwora
/// </summary>
public int ExperiencePoints { get; set; }
/// <summary>
/// Na jakie stany odporny jest potwor
/// </summary>
public string MonsterConditionImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia odporny jest potwor
/// </summary>
public string MonsterDamageImmunities { get; set; }
/// <summary>
/// Na jakie obrazenia potwor ma zmniejszoną słabosc
/// </summary>
public string MonsterDamageResistances { get; set; }
/// <summary>
/// Na co potwor jest wrazliwy
/// </summary>
public string MonsterDamageVulnerabilities { get; set; }
/// <summary>
/// Jezyki jakimi wlada potwor
/// </summary>
public string MonsterLanguages { get; set; }
/// <summary>
/// Połączenie z tabelą MonsterSenses
/// </summary>
public string MonsterSenses { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SessionCompanion.ViewModels.SpecialAbilityViewModels
{
public class SpecialAbilityViewModel
{
public int Id { get; set; }
// <summary>
/// Nazwa umiejętności
/// </summary>
public string Name { get; set; }
/// <summary>
/// Opis umiejętności
/// </summary>
public string Description { get; set; }
public int? DamageDice { get; set; }
public int? DamageDiceAmount { get; set; }
}
}

View File

@ -28,7 +28,7 @@ namespace SessionCompanion.XUnitTests
this.userServiceMock.Setup(p => p.SearchUserByUsername("test")).ReturnsAsync(test); this.userServiceMock.Setup(p => p.SearchUserByUsername("test")).ReturnsAsync(test);
this.userController = new UserController(this.userServiceMock.Object); //this.userController = new UserController(this.userServiceMock.Object);
} }
[Test] [Test]

View File

@ -10,10 +10,13 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.ViewModels", "SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj", "{7762AA75-7B60-4F28-B80A-B03E39140F89}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.ViewModels", "SessionCompanion.ViewModels\SessionCompanion.ViewModels.csproj", "{7762AA75-7B60-4F28-B80A-B03E39140F89}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.Services", "SessionCompanion.Services\SessionCompanion.Services.csproj", "{C0A172ED-0F4C-4E78-8B64-28E2A756F62F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.Services", "SessionCompanion.Services\SessionCompanion.Services.csproj", "{C0A172ED-0F4C-4E78-8B64-28E2A756F62F}"
ProjectSection(ProjectDependencies) = postProject
{1EE35EB3-C703-407C-B390-5605A0A46884} = {1EE35EB3-C703-407C-B390-5605A0A46884}
EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.Extensions", "SessionCompanion.Extensions\SessionCompanion.Extensions.csproj", "{1EE35EB3-C703-407C-B390-5605A0A46884}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.Extensions", "SessionCompanion.Extensions\SessionCompanion.Extensions.csproj", "{1EE35EB3-C703-407C-B390-5605A0A46884}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SessionCompanion.XUnitTests", "SessionCompanion.XUnitTests\SessionCompanion.XUnitTests.csproj", "{B8A4DAF6-DD33-4B35-99B8-A1D060EE1869}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionCompanion.XUnitTests", "SessionCompanion.XUnitTests\SessionCompanion.XUnitTests.csproj", "{B8A4DAF6-DD33-4B35-99B8-A1D060EE1869}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -46,6 +46,9 @@ import { ArmorService } from '../services/armor.service';
import { OtherEquipmentService } from '../services/other-equipment.service'; import { OtherEquipmentService } from '../services/other-equipment.service';
import { ThrowPrimaryAbilityComponent } from './components/throws/throw-primary-ability/throw-primary-ability.component'; import { ThrowPrimaryAbilityComponent } from './components/throws/throw-primary-ability/throw-primary-ability.component';
import { MatRadioModule } from '@angular/material/radio'; import { MatRadioModule } from '@angular/material/radio';
import { GameMasterMonstersTableComponent } from './components/game-master-monsters-table/game-master-monsters-table.component';
import { MonsterService } from '../services/monster.service';
import { SpellDetailsDialogComponent } from './components/spell-details-dialog/spell-details-dialog.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -63,6 +66,8 @@ import { MatRadioModule } from '@angular/material/radio';
GameMasterWeaponsTableComponent, GameMasterWeaponsTableComponent,
GameMasterCharacterActionsDialogComponent, GameMasterCharacterActionsDialogComponent,
ThrowPrimaryAbilityComponent, ThrowPrimaryAbilityComponent,
GameMasterMonstersTableComponent,
SpellDetailsDialogComponent,
], ],
imports: [ imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
@ -99,15 +104,18 @@ import { MatRadioModule } from '@angular/material/radio';
WeaponService, WeaponService,
ArmorService, ArmorService,
OtherEquipmentService, OtherEquipmentService,
MonsterService,
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
entryComponents: [ entryComponents: [
GameMasterSpellsTableComponent, GameMasterSpellsTableComponent,
GameMasterArmorsTableComponent, GameMasterArmorsTableComponent,
GameMasterWeaponsTableComponent, GameMasterWeaponsTableComponent,
GameMasterMonstersTableComponent,
AbilitiesComponent, AbilitiesComponent,
GameMasterCharacterActionsDialogComponent, GameMasterCharacterActionsDialogComponent,
ThrowPrimaryAbilityComponent ThrowPrimaryAbilityComponent,
SpellDetailsDialogComponent,
], ],
}) })
export class AppModule {} export class AppModule {}

View File

@ -6,27 +6,27 @@
<div class="mat-elevation-z8"> <div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort> <table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="Name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td> <td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Category"> <ng-container matColumnDef="category">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Category </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Category </th>
<td mat-cell *matCellDef="let row"> {{row.category}} </td> <td mat-cell *matCellDef="let row"> {{row.category}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="MinimumStrength"> <ng-container matColumnDef="minimumStrength">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Minimum Strength </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Minimum Strength </th>
<td mat-cell *matCellDef="let row"> {{row.minimumStrength}}% </td> <td mat-cell *matCellDef="let row"> {{row.minimumStrength}}% </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Weight"> <ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
<td mat-cell *matCellDef="let row"> {{row.weight}} </td> <td mat-cell *matCellDef="let row"> {{row.weight}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Cost"> <ng-container matColumnDef="cost">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Cost </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Cost </th>
<td mat-cell *matCellDef="let row"> {{row.cost}} $ </td> <td mat-cell *matCellDef="let row"> {{row.cost}} $ </td>
</ng-container> </ng-container>

View File

@ -15,11 +15,11 @@ import { ArmorService } from '../../../services/armor.service';
}) })
export class GameMasterArmorsTableComponent implements OnInit { export class GameMasterArmorsTableComponent implements OnInit {
displayedColumns: string[] = [ displayedColumns: string[] = [
'Name', 'name',
'Category', 'category',
'MinimumStrength', 'minimumStrength',
'Weight', 'weight',
'Cost', 'cost',
]; ];
dataSource: MatTableDataSource<ArmorViewModel>; dataSource: MatTableDataSource<ArmorViewModel>;
@ -40,7 +40,7 @@ export class GameMasterArmorsTableComponent implements OnInit {
if (error instanceof HttpErrorResponse) { if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse; error = error.error as ErrorResponse;
} }
console.log(error.message); console.error(error.message);
} }
); );
} }

View File

@ -41,6 +41,11 @@
</div> </div>
</div> </div>
</div> </div>
<mat-list-item (click)="onLogoutClick()">
<mat-icon matListIcon>exit_to_app</mat-icon>
<span [@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'" class="mat-list-text" style="color: white">Log out</span>
</mat-list-item>
<mat-divider></mat-divider>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content> <mat-sidenav-content>

View File

@ -16,6 +16,11 @@ import { GameMasterArmorsTableComponent } from '../game-master-armors-table/game
import { MatDialog } from '@angular/material'; import { MatDialog } from '@angular/material';
import { GameMasterCharacterActionsDialogComponent } from '../game-master-character-actions-dialog/game-master-character-actions-dialog.component'; import { GameMasterCharacterActionsDialogComponent } from '../game-master-character-actions-dialog/game-master-character-actions-dialog.component';
import { GameMasterWeaponsTableComponent } from '../game-master-weapons-table/game-master-weapons-table.component'; import { GameMasterWeaponsTableComponent } from '../game-master-weapons-table/game-master-weapons-table.component';
import { ClearStore } from '../../store/actions/app.actions';
import { Store } from '@ngrx/store';
import { AppState } from '../../store/models/app-state.model';
import { Router } from '@angular/router';
import { GameMasterMonstersTableComponent } from '../game-master-monsters-table/game-master-monsters-table.component';
@Component({ @Component({
selector: 'app-game-master-dashboard', selector: 'app-game-master-dashboard',
@ -54,6 +59,12 @@ export class GameMasterDashboardComponent implements OnInit, OnDestroy {
componentToDisplay: 'GameMasterSpellsTableComponent', componentToDisplay: 'GameMasterSpellsTableComponent',
expanded: false, expanded: false,
}, },
{
displayName: 'Monsters',
iconName: 'ra ra-wyvern',
componentToDisplay: 'GameMasterMonstersTableComponent',
expanded: false,
},
]; ];
rightSidenavExpanded = false; rightSidenavExpanded = false;
@ -61,6 +72,8 @@ export class GameMasterDashboardComponent implements OnInit, OnDestroy {
loggedCharacters: LoggedCharactersViewModel[]; loggedCharacters: LoggedCharactersViewModel[];
constructor( constructor(
private store: Store<AppState>,
private router: Router,
private signalRService: GMSignalRService, private signalRService: GMSignalRService,
private characterService: CharacterService, private characterService: CharacterService,
public dialog: MatDialog public dialog: MatDialog
@ -126,9 +139,17 @@ export class GameMasterDashboardComponent implements OnInit, OnDestroy {
case 'GameMasterWeaponsTableComponent': case 'GameMasterWeaponsTableComponent':
this.middleComponentName = GameMasterWeaponsTableComponent; this.middleComponentName = GameMasterWeaponsTableComponent;
break; break;
case 'GameMasterMonstersTableComponent':
this.middleComponentName = GameMasterMonstersTableComponent;
break;
} }
} }
onLogoutClick() {
this.store.dispatch(new ClearStore());
this.router.navigate(['/']);
}
private SubscribeToEvents(): void { private SubscribeToEvents(): void {
this.signalRService.message.subscribe((message: string) => { this.signalRService.message.subscribe((message: string) => {
if ( if (

View File

@ -0,0 +1,30 @@
table {
background-color: initial;
}
mat-paginator {
background-color: initial;
color: white;
}
::ng-deep .mat-select-arrow {
color: whitesmoke;
}
::ng-deep .mat-select-value {
color: white;
}
.mat-sort-header-container {
color: whitesmoke !important;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td,
th {
color: whitesmoke;
}

View File

@ -0,0 +1,48 @@
<mat-form-field>
<mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event)" placeholder="Ex. Dragon" #input>
</mat-form-field>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort class="w-100">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Type </th>
<td mat-cell *matCellDef="let row"> {{row.type.charAt(0).toUpperCase() + row.type.slice(1)}} </td>
</ng-container>
<ng-container matColumnDef="subtype">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Subtype </th>
<td mat-cell *matCellDef="let row"> {{row.subtype ? row.subtype.charAt(0).toUpperCase() + row.subtype.slice(1) : row.subtype}} </td>
</ng-container>
<ng-container matColumnDef="alignment">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alignment </th>
<td mat-cell *matCellDef="let row"> {{row.alignment ? row.alignment.charAt(0).toUpperCase() + row.alignment.slice(1) : row.alignment}} </td>
</ng-container>
<ng-container matColumnDef="armorClass">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Armor Class </th>
<td mat-cell *matCellDef="let row"> {{row.armorClass}} </td>
</ng-container>
<ng-container matColumnDef="hitPoints">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Hit Points </th>
<td mat-cell *matCellDef="let row"> {{row.hitPoints}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>

View File

@ -0,0 +1,59 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { MonsterViewModel } from '../../../types/viewmodels/monster-viewmodels/MonsterViewModel';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MonsterService } from '../../../services/monster.service';
import { first } from 'rxjs/operators';
import { ErrorResponse } from '../../../types/ErrorResponse';
import { HttpErrorResponse } from '@angular/common/http';
@Component({
selector: 'app-game-master-monsters-table',
templateUrl: './game-master-monsters-table.component.html',
styleUrls: ['./game-master-monsters-table.component.css'],
})
export class GameMasterMonstersTableComponent implements OnInit {
displayedColumns: string[] = [
'name',
'type',
'subtype',
'alignment',
'armorClass',
'hitPoints',
];
dataSource: MatTableDataSource<MonsterViewModel>;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(private monsterService: MonsterService) {}
ngOnInit() {
this.monsterService
.GetAllMonsters()
.pipe(first())
.subscribe(
(result) => {
this.dataSource = new MatTableDataSource(result);
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
},
(error: ErrorResponse | HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse;
}
console.error(error.message);
}
);
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
}

View File

@ -6,28 +6,28 @@
<div class="mat-elevation-z8"> <div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort> <table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="Name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td> <td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Range"> <ng-container matColumnDef="range">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Range </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Range </th>
<td mat-cell *matCellDef="let row"> {{row.range}} </td> <td mat-cell *matCellDef="let row"> {{row.range}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Level"> <ng-container matColumnDef="level">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Level </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Level </th>
<td mat-cell *matCellDef="let row"> {{row.level}} </td> <td mat-cell *matCellDef="let row"> {{row.level}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="School"> <ng-container matColumnDef="school">
<th mat-header-cell *matHeaderCellDef mat-sort-header> School </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> School </th>
<td mat-cell *matCellDef="let row"> {{row.school}} </td> <td mat-cell *matCellDef="let row"> {{row.school}} </td>
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="ShowSpellDetailsDialog(row.id)"></tr>
<tr class="mat-row" *matNoDataRow> <tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td> <td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>

View File

@ -7,6 +7,8 @@ import { SpellService } from '../../../services/spell.service';
import { first } from 'rxjs/operators'; import { first } from 'rxjs/operators';
import { ErrorResponse } from '../../../types/ErrorResponse'; import { ErrorResponse } from '../../../types/ErrorResponse';
import { HttpErrorResponse } from '@angular/common/http'; import { HttpErrorResponse } from '@angular/common/http';
import { MatDialog } from '@angular/material';
import { SpellDetailsDialogComponent } from '../spell-details-dialog/spell-details-dialog.component';
@Component({ @Component({
selector: 'app-game-master-spells-table', selector: 'app-game-master-spells-table',
@ -14,13 +16,13 @@ import { HttpErrorResponse } from '@angular/common/http';
styleUrls: ['./game-master-spells-table.component.css'], styleUrls: ['./game-master-spells-table.component.css'],
}) })
export class GameMasterSpellsTableComponent implements OnInit { export class GameMasterSpellsTableComponent implements OnInit {
displayedColumns: string[] = ['Name', 'Range', 'Level', 'School']; displayedColumns: string[] = ['name', 'range', 'level', 'school'];
dataSource: MatTableDataSource<SpellViewModel>; dataSource: MatTableDataSource<SpellViewModel>;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort; @ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(private spellService: SpellService) { constructor(private spellService: SpellService, public dialog: MatDialog) {
spellService spellService
.GetAllSpells() .GetAllSpells()
.pipe(first()) .pipe(first())
@ -34,7 +36,7 @@ export class GameMasterSpellsTableComponent implements OnInit {
if (error instanceof HttpErrorResponse) { if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse; error = error.error as ErrorResponse;
} }
console.log(error.message); console.error(error.message);
} }
); );
} }
@ -49,4 +51,9 @@ export class GameMasterSpellsTableComponent implements OnInit {
this.dataSource.paginator.firstPage(); this.dataSource.paginator.firstPage();
} }
} }
ShowSpellDetailsDialog(spellId: number) {
let spell = this.dataSource.data.find((e) => e.id == spellId);
this.dialog.open(SpellDetailsDialogComponent, { data: { spell: spell } });
}
} }

View File

@ -6,27 +6,27 @@
<div class="mat-elevation-z8"> <div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort class="w-100"> <table mat-table [dataSource]="dataSource" matSort class="w-100">
<ng-container matColumnDef="Name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td> <td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="WeaponType"> <ng-container matColumnDef="weaponType">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weapon Type </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Weapon Type </th>
<td mat-cell *matCellDef="let row"> {{row.weaponType}} </td> <td mat-cell *matCellDef="let row"> {{row.weaponType}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Weight"> <ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
<td mat-cell *matCellDef="let row"> {{row.weight}} </td> <td mat-cell *matCellDef="let row"> {{row.weight}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Cost"> <ng-container matColumnDef="cost">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Cost </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Cost </th>
<td mat-cell *matCellDef="let row"> {{row.cost}} $ </td> <td mat-cell *matCellDef="let row"> {{row.cost}} $ </td>
</ng-container> </ng-container>
<ng-container matColumnDef="Description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Description </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> Description </th>
<td mat-cell *matCellDef="let row" class="text-cut" [matTooltip]="row.description"> <td mat-cell *matCellDef="let row" class="text-cut" [matTooltip]="row.description">
{{row.description}} {{row.description}}

View File

@ -15,11 +15,11 @@ import { HttpErrorResponse } from '@angular/common/http';
}) })
export class GameMasterWeaponsTableComponent implements OnInit { export class GameMasterWeaponsTableComponent implements OnInit {
displayedColumns: string[] = [ displayedColumns: string[] = [
'Name', 'name',
'WeaponType', 'weaponType',
'Weight', 'weight',
'Cost', 'cost',
'Description', 'description',
]; ];
dataSource: MatTableDataSource<WeaponViewModel>; dataSource: MatTableDataSource<WeaponViewModel>;
@ -40,7 +40,7 @@ export class GameMasterWeaponsTableComponent implements OnInit {
if (error instanceof HttpErrorResponse) { if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse; error = error.error as ErrorResponse;
} }
console.log(error.message); console.error(error.message);
} }
); );
} }

View File

@ -40,7 +40,7 @@
<a matLine>Shop</a> <a matLine>Shop</a>
</mat-list-item> </mat-list-item>
<mat-list-item [routerLink]="['/']" [routerLinkActive]="['active']"> <mat-list-item (click)="onLogoutClick()">
<mat-icon [class.active]="selected" matListIcon>exit_to_app</mat-icon> <mat-icon [class.active]="selected" matListIcon>exit_to_app</mat-icon>
<a matLine>Log out</a> <a matLine>Log out</a>
</mat-list-item> </mat-list-item>

View File

@ -1,9 +1,12 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { PlayerSignalRService } from "../../shared/signalR-service/player-signalR.service"; import { PlayerSignalRService } from '../../shared/signalR-service/player-signalR.service';
import { first } from "rxjs/operators"; import { first } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from 'src/app/store/models/app-state.model'; import { AppState } from 'src/app/store/models/app-state.model';
import { AbilitiesComponent } from '../abilities/abilities.component'; import { AbilitiesComponent } from '../abilities/abilities.component';
import {ClearStore, ClearUserId} from '../../store/actions/app.actions';
import { Router } from '@angular/router';
import {ClearCharacterId} from "../../store/actions/player.action";
@Component({ @Component({
selector: 'app-player-dashboard', selector: 'app-player-dashboard',
@ -15,13 +18,13 @@ export class PlayerDashboardComponent implements OnInit {
isExpanded = false; isExpanded = false;
selected = false; selected = false;
constructor(private signalRService: PlayerSignalRService, private store: Store<AppState>) {} constructor(private signalRService: PlayerSignalRService, private store: Store<AppState>, private router: Router) {}
ngOnInit() { ngOnInit() {
this.store.select(s => s.playerStore.characterId).pipe(first()).subscribe((id) => { this.store.select(s => s.playerStore.characterId).pipe(first()).subscribe((id) => {
this.signalRService.Login(id); this.signalRService.Login(id);
});
this.SwitchMiddleComponent('AbilitiesComponent'); this.SwitchMiddleComponent('AbilitiesComponent');
});
} }
toggle() { toggle() {
@ -29,9 +32,15 @@ export class PlayerDashboardComponent implements OnInit {
} }
SwitchMiddleComponent(componentName: string) { SwitchMiddleComponent(componentName: string) {
switch(componentName){ switch (componentName) {
case 'AbilitiesComponent': case 'AbilitiesComponent':
this.middleComponent = AbilitiesComponent; this.middleComponent = AbilitiesComponent;
} }
} }
onLogoutClick() {
this.store.dispatch(new ClearCharacterId());
this.store.dispatch(new ClearStore());
this.router.navigate(['/']);
}
} }

View File

@ -0,0 +1,38 @@
.spell-card-flag {
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0 0);
width: 70px;
height: 150px;
}
.shadow-for-flag {
right: 5%;
position: absolute;
filter: drop-shadow(0px 0px 3px white);
}
.names-on-flag {
height: 18px;
font-size: 15px !important;
text-align: center;
}
::ng-deep mat-dialog-container {
padding: 0 !important;
}
::ng-deep mat-card {
padding: 0 !important;
}
mat-icon {
vertical-align: middle;
}
.spell-details-card {
color: whitesmoke;
background-color: lightgray;
max-width: 600px;
}
.spell-details-card > mat-card-header {
background-color: #3d4751;
}
.spell-details-card > mat-card-content {
background-color: #4f5c69;
}
::-webkit-scrollbar {
display: none;
}

View File

@ -0,0 +1,49 @@
<mat-card class="spell-details-card">
<mat-card-header>
<div style="margin-top: 10px">
<mat-card-title>{{spell.name}}</mat-card-title>
</div>
<div class="shadow-for-flag">
<div class="spell-card-flag" [ngStyle]="{backgroundColor: spellFlagBackgroundColor}">
<div *ngFor="let elem of spell.classes" class="names-on-flag">{{elem}}</div>
<div *ngFor="let elem of spell.subclasses" class="names-on-flag">{{elem}}</div>
</div>
</div>
</mat-card-header>
<mat-card-content style="padding-left: 10px; padding-right: 10px;overflow-y: auto; max-height: 600px;-ms-overflow-style: none; scrollbar-width: none;">
<br/>
<div style="font-style: italic;">{{GetSpellLevelAndSchool()}}</div>
<hr />
<div>
<mat-icon inline style="font-size: 16px;" color="white">history_toggle_off</mat-icon> Casting Time: {{spellDictionary.GetCastingTime(spell.castingTime)}}
</div>
<div>
<mat-icon inline style="font-size: 16px;" color="white"><i class="ra ra-archery-target"></i></mat-icon> Range: {{spellDictionary.GetRange(spell.range)}}
</div>
<div>
<mat-icon inline style="font-size: 16px;" color="white">hourglass_bottom</mat-icon> Duration: {{spellDictionary.GetDuration(spell.duration)}}
</div>
<hr />
<b>Description:</b>
<p style="text-align: justify;">{{GetSpellDescription()}}</p>
<div *ngIf="spell.higherLevel.length > 0">
<b>At Higher Levels:</b>
<p style="text-align: justify;">{{GetSpellAtHigherLevels()}}</p>
</div>
<hr />
<div *ngIf="spell.components.length > 0">
<table style="border-spacing: 10px 0; border-collapse: unset">
<tr>
<td *ngIf="spell.components.includes('V')" style="text-align: center;"><mat-icon style="font-size: 34px; width: 34px; height: 34px">volume_up</mat-icon></td>
<td *ngIf="spell.components.includes('S')" style="text-align: center;"><mat-icon style="font-size: 34px; width: 34px; height: 34px">gesture</mat-icon></td>
<td *ngIf="spell.components.includes('M')" style="text-align: center;" [matTooltip]="spell.material"><mat-icon style="font-size: 34px; width: 34px; height: 34px">extension</mat-icon></td>
</tr>
<tr>
<td *ngIf="spell.components.includes('V')">Verbal</td>
<td *ngIf="spell.components.includes('S')">Somatic</td>
<td *ngIf="spell.components.includes('M')">Material</td>
</tr>
</table>
</div>
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,96 @@
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { SpellViewModel } from '../../../types/viewmodels/spell-viewmodels/SpellViewModel';
import SpellDictionary from '../../shared/dictionaries/SpellDictionary';
@Component({
selector: 'app-spell-details-dialog',
templateUrl: './spell-details-dialog.component.html',
styleUrls: ['./spell-details-dialog.component.css'],
})
export class SpellDetailsDialogComponent implements OnInit {
spell: SpellViewModel;
spellFlagBackgroundColor: string;
spellDictionary = SpellDictionary;
constructor(
public dialogRef: MatDialogRef<SpellDetailsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
ngOnInit() {
this.spell = this.data.spell;
this.ChangeFlagColor();
}
GetSpellDescription() {
let result = '';
for (let elem of this.spell.descriptions) {
result += elem;
}
return result;
}
GetSpellAtHigherLevels() {
let result = '';
for (let elem of this.spell.higherLevel) {
result += elem;
}
return result;
}
GetSpellLevelAndSchool() {
let result = '';
if (this.spell.level == -1) {
result += this.spell.school + ' Cantrip';
} else {
result += this.spell.level + ' st level ' + this.spell.school;
}
if (this.spell.ritual) {
result += ' (ritual)';
}
return result;
}
ChangeFlagColor() {
switch (this.spell.school) {
case 'Evocation': {
this.spellFlagBackgroundColor = '#7c081e';
break;
}
case 'Conjuration': {
this.spellFlagBackgroundColor = '#335f96';
break;
}
case 'Abjuration': {
this.spellFlagBackgroundColor = '#bab725';
break;
}
case 'Transmutation': {
this.spellFlagBackgroundColor = '#875a2d';
break;
}
case 'Enchantment': {
this.spellFlagBackgroundColor = '#479636';
break;
}
case 'Necromancy': {
this.spellFlagBackgroundColor = '#444444';
break;
}
case 'Divination': {
this.spellFlagBackgroundColor = '#a1a3a3';
break;
}
case 'Illusion': {
this.spellFlagBackgroundColor = '#652d84';
break;
}
default: {
this.spellFlagBackgroundColor = '#212b87';
break;
}
}
}
}

View File

@ -0,0 +1,59 @@
const Ranges: { [key: string]: string } = {
Self: 'Self',
Touch: 'Touch',
Special: 'Special',
Sight: 'Slight',
Unlimited: 'Unlimited',
Feet_5: '5 Feet',
Feet_10: '10 Feet',
Feet_30: '30 Feet',
Feet_60: '60 Feet',
Feet_90: '90 Feet',
Feet_100: '100 Feet',
Feet_120: '120 Feet',
Feet_150: '150 Feet',
Feet_300: '300 Feet',
Feet_500: '500 Feet',
Miles_1: '1 Mile',
Miles_500: '500 Miles',
};
const Durations: { [key: string]: string } = {
Instantaneous: 'Instantaneous',
Until_dispelled: 'Until dispeled',
Special: 'Special',
Minutes_1: '1 Minute',
Minutes_10: '10 Minutes',
Hours_1: '1 Hour',
Hours_2: '2 Hours',
Hours_8: '8 Hours',
Hours_24: '24 Hours',
Days_7: '7 Days',
Days_10: '10 Days',
Days_30: '30 Days',
Round_1: '1 Round',
};
const CastingTimes: { [key: string]: string } = {
Minutes_1: '1 Minute',
Minutes_10: '10 Minutes',
Hours_1: '1 Hour',
Hours_8: '8 Hours',
Hours_12: '12 Hours',
Hours_24: '24 Hours',
Action_1: '1 Action',
Reaction_1: '1 Reaction',
Bonus_Action_1: '1 Bonus Action',
};
export default new (class SpellDictionary {
GetRange(name: string) {
return Ranges[name];
}
GetDuration(name: string) {
return Durations[name];
}
GetCastingTime(name: string) {
return CastingTimes[name];
}
})();

View File

@ -3,7 +3,8 @@ import {Action} from '@ngrx/store';
export enum AppActionTypes { export enum AppActionTypes {
ADD_USER_ID = '[APP] Add user id', ADD_USER_ID = '[APP] Add user id',
ADD_ROLE = '[APP] Add role', ADD_ROLE = '[APP] Add role',
CLEAR_USER_ID = '[APP] Clear user id' CLEAR_USER_ID = '[APP] Clear user id',
CLEAR_STORE = '[APP] Clear user id and user role'
} }
export class AddUserId implements Action { export class AddUserId implements Action {
@ -27,6 +28,12 @@ export class ClearUserId implements Action {
} }
} }
export class ClearStore implements Action {
readonly type = AppActionTypes.CLEAR_STORE;
constructor() {
}
}
export type AppAction = AddUserId | AddRole | ClearUserId; export type AppAction = AddUserId | AddRole | ClearUserId | ClearStore;

View File

@ -1,7 +1,8 @@
import {Action} from "@ngrx/store"; import {Action} from '@ngrx/store';
export enum PlayerActionTypes { export enum PlayerActionTypes {
ADD_CHARACTER_ID= '[PLAYER] Add character id' ADD_CHARACTER_ID= '[PLAYER] Add character id',
CLEAR_CHARACTER_ID = '[PLAYER] Clear character id'
} }
export class AddCharacterId implements Action { export class AddCharacterId implements Action {
@ -12,4 +13,12 @@ export class AddCharacterId implements Action {
} }
} }
export type PlayerAction = AddCharacterId; export class ClearCharacterId implements Action {
readonly type = PlayerActionTypes.CLEAR_CHARACTER_ID;
constructor() {
}
}
export type PlayerAction = AddCharacterId | ClearCharacterId;

View File

@ -14,6 +14,8 @@ export function AppReducer(state: AppStoreModel = initialState, action: AppActio
return {...state, role: action.payload.role}; return {...state, role: action.payload.role};
case AppActionTypes.CLEAR_USER_ID: case AppActionTypes.CLEAR_USER_ID:
return {...state, userId: null}; return {...state, userId: null};
case AppActionTypes.CLEAR_STORE:
return {userId: null, role: null};
default: default:
return state; return state;
} }

View File

@ -9,6 +9,8 @@ export function PlayerReducer(state: PlayerStoreModel = initialState, action: Pl
switch (action.type) { switch (action.type) {
case PlayerActionTypes.ADD_CHARACTER_ID: case PlayerActionTypes.ADD_CHARACTER_ID:
return {...state, characterId: action.payload.characterId}; return {...state, characterId: action.payload.characterId};
case PlayerActionTypes.CLEAR_CHARACTER_ID:
return { characterId: null};
default: default:
return state; return state;
} }

View File

@ -0,0 +1,34 @@
import { Inject, Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { SpellViewModel } from '../types/viewmodels/spell-viewmodels/SpellViewModel';
import { Either } from '../types/Either';
import { ErrorResponse } from '../types/ErrorResponse';
import { switchMap } from 'rxjs/operators';
import { MonsterViewModel } from '../types/viewmodels/monster-viewmodels/MonsterViewModel';
Injectable({
providedIn: 'root',
});
export class MonsterService {
private baseUrl = 'api/monster/';
constructor(private http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
this.baseUrl = baseUrl + this.baseUrl;
}
GetAllMonsters(): Observable<MonsterViewModel[]> {
return this.http
.get<Either<MonsterViewModel[], ErrorResponse>>(
this.baseUrl + 'getAllMonsters'
)
.pipe(
switchMap((response) => {
if (response.isLeft) {
return of(response.left);
} else {
return throwError(response.right);
}
})
);
}
}

View File

@ -0,0 +1,35 @@
export interface MonsterViewModel {
id: number;
name: string;
size: string;
type: string;
subtype: string;
alignment: string;
armorClass: number;
hitPoints: number;
hitDiceAmount: number;
hitDiceType: number;
walkSpeed: string;
swimSpeed: string;
flySpeed: string;
dexterity: number;
dexteritySave?: number;
strength: number;
strengthSave?: number;
constitution: number;
constitutionSave?: number;
intelligence: number;
intelligenceSave?: number;
wisdom: number;
wisdomSave?: number;
charisma: number;
charismaSave?: number;
challengeRating: number;
experiencePoints: number;
monsterConditionImmunities: string;
monsterDamageImmunities: string;
monsterDamageResistances: string;
monsterDamageVulnerabilities: string;
monsterLanguages: string;
monsterSenses: string;
}

View File

@ -36,6 +36,13 @@ namespace SessionCompanion.Configurations
services.AddScoped<IRepository<CharacterOtherEquipment>, CharacterOtherEquipmentRepository>(); services.AddScoped<IRepository<CharacterOtherEquipment>, CharacterOtherEquipmentRepository>();
services.AddScoped<IRepository<Weapon>, WeaponRepository>(); services.AddScoped<IRepository<Weapon>, WeaponRepository>();
services.AddScoped<IRepository<CharacterWeapon>, CharacterWeaponRepository>(); services.AddScoped<IRepository<CharacterWeapon>, CharacterWeaponRepository>();
services.AddScoped<IRepository<GameAction>, GameActionRepository>();
services.AddScoped<IRepository<LegendaryAction>, LegendaryActionRepository>();
services.AddScoped<IRepository<MonsterAction>, MonsterActionsRepository>();
services.AddScoped<IRepository<MonsterLegendaryAction>, MonsterLegendaryActionsRepository>();
services.AddScoped<IRepository<Monster>, MonsterRepository>();
services.AddScoped<IRepository<MonsterSpecialAbility>, MonsterSpecialAbilitiesRepository>();
services.AddScoped<IRepository<SpecialAbility>, SpecialAbilityRepository>();
return services; return services;
} }
} }

View File

@ -35,6 +35,7 @@ namespace SessionCompanion.Configurations
services.AddScoped<ICharacterOtherEquipmentService, CharacterOtherEquipmentService>(); services.AddScoped<ICharacterOtherEquipmentService, CharacterOtherEquipmentService>();
services.AddScoped<IWeaponService, WeaponService>(); services.AddScoped<IWeaponService, WeaponService>();
services.AddScoped<ICharacterWeaponService, CharacterWeaponService>(); services.AddScoped<ICharacterWeaponService, CharacterWeaponService>();
services.AddScoped<IMonsterService, MonsterService>();
return services; return services;
} }

View File

@ -9,6 +9,7 @@ namespace SessionCompanion.Controllers
{ {
using SessionCompanion.Hubs; using SessionCompanion.Hubs;
using SessionCompanion.ViewModels.UniversalModels; using SessionCompanion.ViewModels.UniversalModels;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
@ -19,11 +20,15 @@ namespace SessionCompanion.Controllers
{ {
private readonly ICharacterService _service; private readonly ICharacterService _service;
private readonly SessionHubData _sessionHubData; private readonly SessionHubData _sessionHubData;
private readonly IRaceService _raceService;
private readonly IClassService _classService;
public CharacterController(ICharacterService service) public CharacterController(ICharacterService service, IRaceService raceService, IClassService classService)
{ {
this._service = service; this._service = service;
this._sessionHubData = new SessionHubData(); this._sessionHubData = new SessionHubData();
this._raceService = raceService;
this._classService = classService;
} }
/// <summary> /// <summary>
@ -105,5 +110,53 @@ namespace SessionCompanion.Controllers
}; };
return info; return info;
} }
/// <summary>
/// Metoda zwraca podstawowe informacje dla postaci z Templatek
/// </summary>
/// <returns>liste podstawowych informacji o postaciach z templatki</returns>
[HttpGet("getTemplateCharacters")]
public async Task<Either<ErrorResponse, List<CharacterFromTemplatesSimpleViewModel>>> GetTemplateCharacters()
{
var races = _raceService.Get().ToList();
var classes = _classService.Get().ToList();
try
{
var templateCharacters = await _service.GetCharactersFromTemplate(races, classes);
return templateCharacters.ToList();
}
catch (Exception e)
{
return new ErrorResponse()
{
StatusCode = 500,
Message = e.Message
};
}
}
/// <summary>
/// Metoda do tworzenia postaci z templatek
/// </summary>
/// <param name="characterId">Id postaci z templatki</param>
/// <param name="userId"></param>
/// <param name="newName"></param>
/// <returns></returns>
[HttpPost("createCharacterFromTemplate")]
public async Task<Either<SuccessResponse,ErrorResponse>> CreateTemplateCharacters(int characterId, int userId, string newName)
{
try
{
await _service.CreateCharactersFromTemplate(characterId, userId, newName);
return new SuccessResponse("Character created") { SuccessCode = 200 };
}
catch (Exception e)
{
return new ErrorResponse()
{
StatusCode = 500,
Message = e.Message
};
}
}
} }
} }

View File

@ -0,0 +1,145 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SessionCompanion.Controllers
{
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.Services.Interfaces;
using SessionCompanion.ViewModels.ApiResponses;
using SessionCompanion.ViewModels.CharacterArmorViewModels;
using SessionCompanion.ViewModels.CharacterOtherEquipmentViewModels;
using SessionCompanion.ViewModels.CharacterWeaponViewModels;
[Route("api/character/equipment")]
[ApiController]
public class EquipmentController : Controller
{
private readonly ICharacterArmorService _characterArmorService;
private readonly ICharacterOtherEquipmentService _characterOtherEquipmentService;
private readonly ICharacterWeaponService _characterWeaponService;
public EquipmentController(ICharacterArmorService characterArmorService,
ICharacterOtherEquipmentService characterOtherEquipmentService,
ICharacterWeaponService characterWeaponService)
{
this._characterArmorService = characterArmorService;
this._characterOtherEquipmentService = characterOtherEquipmentService;
this._characterWeaponService = characterWeaponService;
}
/// <summary>
/// Zwraca listę pozostałego ekwipunku dla danej postaci
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista pozostałego ekwipunku lub błąd </returns>
[HttpGet("getOtherEquipment")]
public async Task<Either<List<CharacterOtherEquipmentWithDetailsViewModel>, ErrorResponse>> GetCharacterOtherEquipment(int characterId)
{
return await this._characterOtherEquipmentService.GetCharacterOtherEquipmentList(characterId);
}
/// <summary>
/// Zwraca listę pancerzy posiadanych przez daną postać
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista pozostałego ekwipunku lub błąd </returns>
[HttpGet("getArmors")]
public async Task<Either<List<CharacterArmorViewModelDetails>, ErrorResponse>> GetCharacterArmors(int characterId)
{
return await this._characterArmorService.GetCharacterArmorsTaskList(characterId);
}
/// <summary>
/// Zwraca listę broni posiadanej przez daną postać
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <returns> Lista broni lub błąd </returns>
[HttpGet("getWeapons")]
public async Task<Either<List<CharacterWeaponWithWeaponDetailsViewModel>, ErrorResponse>> GetCharacterWeapons(int characterId)
{
return await this._characterWeaponService.GetCharacterWeaponsList(characterId);
}
/// <summary>
/// Metoda zmienia uzywaną zbroję danej postaci na taki jaki jest wybrany
/// </summary>
/// <param name="characterId"> Id postaci </param>
/// <param name="newArmorId"> Id nowej zbroi </param>
/// <returns>SuccessResponse/ErrorResponse</returns>
[HttpPut("changeArmor")]
public async Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterArmor(int characterId, int newArmorId)
{
var response = await _characterArmorService.ChangeCharacterArmor(characterId, newArmorId);
return response;
}
/// <summary>
/// Metoda dodaje nową zbroje do danej postaci
/// </summary>
/// <param name="characterArmorViewModel"> View model z odpowiednimi parameterami </param>
/// <returns>SuccessResponse/ErrorResponse</returns>
[HttpPut("addArmor")]
public async Task<Either<SuccessResponse, ErrorResponse>> AddCharacterArmor(CharacterArmorViewModel characterArmorViewModel)
{
if (!ModelState.IsValid)
return new ErrorResponse() { StatusCode = 500, Message = "Invalid model!" };
try
{
await _characterArmorService.Create(characterArmorViewModel);
await _characterArmorService.SaveAsync();
return new SuccessResponse("Armor added to character") { SuccessCode = 200 };
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
}
/// <summary>
/// Metoda dodaje broń do danej postaci
/// </summary>
/// <param name="characterWeaponViewModel"> View model z odpowiednimi parameterami </param>
/// <returns>SuccessResponse/ErrorResponse</returns>
[HttpPut("addWeapon")]
public async Task<Either<SuccessResponse, ErrorResponse>> AddCharacterWeapon(CharacterWeaponViewModel characterWeaponViewModel)
{
if (!ModelState.IsValid)
return new ErrorResponse() { StatusCode = 500, Message = "Invalid model!" };
try
{
await _characterWeaponService.Create(characterWeaponViewModel);
await _characterWeaponService.SaveAsync();
return new SuccessResponse("Weapon added to character") { SuccessCode = 200 };
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
}
/// <summary>
/// Metoda zmienia broń do danej postaci
/// </summary>
/// <param name=characterWeaponViewModel> View model z odpowiednimi parameterami </param>
/// <returns>SuccessResponse/ErrorResponse</returns>
[HttpPut("changeWeapon")]
public async Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterWeapon(CharacterWeaponViewModel characterWeaponViewModel)
{
if (!ModelState.IsValid)
return new ErrorResponse() { StatusCode = 500, Message = "Invalid model!" };
try
{
var response = await _characterWeaponService.ChangeCharacterWeapon(characterWeaponViewModel);
return response;
}
catch (Exception e)
{
return new ErrorResponse() { StatusCode = 500, Message = e.Message };
}
}
}
}

View File

@ -0,0 +1,42 @@
using Microsoft.AspNetCore.Mvc;
using SessionCompanion.Extensions.EitherType;
using SessionCompanion.Services.Interfaces;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using SessionCompanion.ViewModels.ApiResponses;
namespace SessionCompanion.Controllers
{
using SessionCompanion.ViewModels.MonsterViewModels;
[Route("api/monster")]
[ApiController]
public class MonsterController : Controller
{
private readonly IMonsterService _service;
public MonsterController(IMonsterService service) => _service = service;
/// <summary>
/// Metoda zwraca wszystkich przeciwników
/// </summary>
/// <returns>Lista wszystkich przeciwników w bazie danych</returns>
[HttpGet("getAllMonsters")]
public Either<List<MonsterViewModel>, ErrorResponse> GetAllMonsters()
{
try
{
return _service.GetAllMonstersList();
}
catch (Exception e)
{
return new ErrorResponse()
{
StatusCode = 204,
Message = e.Message
};
}
}
}
}

View File

@ -6,13 +6,16 @@ using System.Threading.Tasks;
namespace SessionCompanion.Controllers namespace SessionCompanion.Controllers
{ {
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy; using System.Security.Policy;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using SessionCompanion.Database.Tables;
using SessionCompanion.Extensions.EitherType; using SessionCompanion.Extensions.EitherType;
using SessionCompanion.Hubs; using SessionCompanion.Hubs;
using SessionCompanion.ViewModels.ApiResponses; using SessionCompanion.ViewModels.ApiResponses;
using SessionCompanion.ViewModels.CharacterViewModels;
using SessionCompanion.ViewModels.UserViewModels; using SessionCompanion.ViewModels.UserViewModels;
[Route("api/user")] [Route("api/user")]
@ -20,13 +23,15 @@ namespace SessionCompanion.Controllers
public class UserController : Controller public class UserController : Controller
{ {
private readonly IUserService _service; private readonly IUserService _service;
private readonly ICharacterService _characterService;
private SessionHubData _sessionHubData; private SessionHubData _sessionHubData;
public UserController(IUserService service) public UserController(IUserService service, ICharacterService characterService)
{ {
this._service = service; this._service = service;
this._sessionHubData = new SessionHubData(); this._sessionHubData = new SessionHubData();
this._characterService = characterService;
} }
/// <summary> /// <summary>
@ -41,14 +46,32 @@ namespace SessionCompanion.Controllers
UserViewModel user = await _service.SearchUserByUsername(userName); UserViewModel user = await _service.SearchUserByUsername(userName);
if (user != null && user.Password.Equals(password)) if (user != null && user.Password.Equals(password))
return user.Id; {
List<int> userCharactersIds = _characterService.Get(c => c.UserId.Equals(user.Id)).Result.Select(c => c.Id).ToList();
foreach(int characterId in userCharactersIds)
{
if (SessionHubData.ConnectedCharacters.ContainsKey(characterId))
{
return new ErrorResponse()
{
StatusCode = 403,
Message = "User is already logged in"
};
}
}
return user.Id;
}
else
{
return new ErrorResponse() return new ErrorResponse()
{ {
StatusCode = 403, StatusCode = 403,
Message = "User name not found or incorrect password" Message = "User name not found or incorrect password"
}; };
} }
}
/// <summary> /// <summary>