<commit_before>using System;
using System.Collections.Generic;
using System.Data.Entity.Validation;
using System.Linq;
using System.Security.Permissions;
using System.Threading.Tasks;
using JetBrains.Annotations;
using JoinRpg.Data.Interfaces;
using JoinRpg.Data.Write.Interfaces;
using JoinRpg.DataModel;
using JoinRpg.Domain;
using JoinRpg.Helpers;
using JoinRpg.Services.Interfaces;

namespace JoinRpg.Services.Impl
{
    [UsedImplicitly]
    internal class ProjectService : DbServiceImplBase, IProjectService
    {


        public ProjectService(IUnitOfWork unitOfWork) : base(unitOfWork)
        {
        }

        public async Task<Project> AddProject(CreateProjectRequest request)
        {
            var rootGroup = new CharacterGroup()
            {
                IsPublic = true,
                IsRoot = true,
                //TODO[Localize]
                CharacterGroupName = "Все роли",
                IsActive = true,
                ResponsibleMasterUserId = CurrentUserId,
                HaveDirectSlots = true,
                AvaiableDirectSlots = -1,
            };
            MarkCreatedNow(rootGroup);
            var project = new Project()
            {
                Active = true,
                IsAcceptingClaims = false,
                CreatedDate = Now,
                ProjectName = Required(request.ProjectName),
                CharacterGroups = new List<CharacterGroup>()
                {
                    rootGroup,
                },
                ProjectAcls = new List<ProjectAcl>()
                {
                    ProjectAcl.CreateRootAcl(CurrentUserId, isOwner: true),
                },
                Details = new ProjectDetails(),
                ProjectFields = new List<ProjectField>(),
            };
            MarkTreeModified(project);
            switch (request.ProjectType)
            {
                case ProjectTypeDto.Larp:
                    
                    project.Details.CharacterNameLegacyMode = false;
                    project.Details.CharacterNameField = new ProjectField()
                    {
                        CanPlayerEdit = false,
                        CanPlayerView = true,
                        FieldBoundTo = FieldBoundTo.Character,
                        FieldName = "Имя персонажа", //TODO[Localize]
                        FieldType = ProjectFieldType.String,
                        IsActive = true,
                        IsPublic = true,
                        MandatoryStatus = MandatoryStatus.Required,
                        IncludeInPrint = false,
                        ValidForNpc = true,
                        ProjectFieldId = -2,
                        Description = new MarkdownString(""),
                        MasterDescription = new MarkdownString(""),
                    };
                    project.Details.CharacterDescription = new ProjectField()
                    {
                        CanPlayerEdit = false,
                        CanPlayerView = true,
                        FieldBoundTo = FieldBoundTo.Character,
                        FieldName = "Описание персонажа", //TODO[Localize]
                        FieldType = ProjectFieldType.Text,
                        IsActive = true,
                        IsPublic = true,
                        MandatoryStatus = MandatoryStatus.Optional,
                        IncludeInPrint = false,
                        ValidForNpc = true,
                        ProjectFieldId = -1,
                        Description = new MarkdownString(""),
                        MasterDescription = new MarkdownString(""),
                    };

                    project.ProjectFields.Add(project.Details.CharacterNameField);

                    project.ProjectFields.Add(project.Details.CharacterDescription);
                    break;
                case ProjectTypeDto.Convention:
                    project.Details.AutoAcceptClaims = true;
                    project.Details.EnableAccommodation = true;
                    project.Details.CharacterNameLegacyMode = false;
                    project.Details.CharacterNameField = null;
                    project.Details.CharacterDescription = null;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            UnitOfWork.GetDbSet<Project>().Add(project);
            await UnitOfWork.SaveChangesAsync();
            return project;
        }


        public async Task AddCharacterGroup(int projectId,
            string name,
            bool isPublic,
            IReadOnlyCollection<int> parentCharacterGroupIds,
            string description,
            bool haveDirectSlotsForSave,
            int directSlotsForSave,
            int? responsibleMasterId)
        {
            var project = await ProjectRepository.GetProjectAsync(projectId);

            if (responsibleMasterId != null &&
                project.ProjectAcls.All(acl => acl.UserId != responsibleMasterId))
            {
                //TODO: Move this check into ChGroup validation
                throw new Exception("No such master");
            }

            project.RequestMasterAccess(CurrentUserId, acl => acl.CanEditRoles);
            project.EnsureProjectActive();

            Create(new CharacterGroup()
            {
                AvaiableDirectSlots = directSlotsForSave,
                HaveDirectSlots = haveDirectSlotsForSave,
                CharacterGroupName = Required(name),
                ParentCharacterGroupIds =
                    await ValidateCharacterGroupList(projectId,
                        Required(() => parentCharacterGroupIds)),<commit_msg>extract project defaults config to separate method<commit_after>using System;
using System.Collections.Generic;
using System.Data.Entity.Validation;
using System.Linq;
using System.Security.Permissions;
using System.Threading.Tasks;
using JetBrains.Annotations;
using JoinRpg.Data.Interfaces;
using JoinRpg.Data.Write.Interfaces;
using JoinRpg.DataModel;
using JoinRpg.Domain;
using JoinRpg.Helpers;
using JoinRpg.Services.Interfaces;

namespace JoinRpg.Services.Impl
{
    [UsedImplicitly]
    internal class ProjectService : DbServiceImplBase, IProjectService
    {


        public ProjectService(IUnitOfWork unitOfWork) : base(unitOfWork)
        {
        }

        public async Task<Project> AddProject(CreateProjectRequest request)
        {
            var rootGroup = new CharacterGroup()
            {
                IsPublic = true,
                IsRoot = true,
                //TODO[Localize]
                CharacterGroupName = "Все роли",
                IsActive = true,
                ResponsibleMasterUserId = CurrentUserId,
                HaveDirectSlots = true,
                AvaiableDirectSlots = -1,
            };
            MarkCreatedNow(rootGroup);
            var project = new Project()
            {
                Active = true,
                IsAcceptingClaims = false,
                CreatedDate = Now,
                ProjectName = Required(request.ProjectName),
                CharacterGroups = new List<CharacterGroup>()
                {
                    rootGroup,
                },
                ProjectAcls = new List<ProjectAcl>()
                {
                    ProjectAcl.CreateRootAcl(CurrentUserId, isOwner: true),
                },
                Details = new ProjectDetails()
                {
                    CharacterNameLegacyMode = false,
                },
                ProjectFields = new List<ProjectField>(),
            };
            MarkTreeModified(project);
            ConfigureProjectDefaults(project, request.ProjectType);

            UnitOfWork.GetDbSet<Project>().Add(project);
            await UnitOfWork.SaveChangesAsync();
            return project;
        }

        private static void ConfigureProjectDefaults(Project project, ProjectTypeDto projectType)
        {
            switch (projectType)
            {
                case ProjectTypeDto.Larp:

                    project.Details.CharacterNameField = new ProjectField()
                    {
                        CanPlayerEdit = false,
                        CanPlayerView = true,
                        FieldBoundTo = FieldBoundTo.Character,
                        FieldName = "Имя персонажа", //TODO[Localize]
                        FieldType = ProjectFieldType.String,
                        IsActive = true,
                        IsPublic = true,
                        MandatoryStatus = MandatoryStatus.Required,
                        IncludeInPrint = false,
                        ValidForNpc = true,
                        ProjectFieldId = -2,
                        Description = new MarkdownString(""),
                        MasterDescription = new MarkdownString(""),
                    };
                    project.Details.CharacterDescription = new ProjectField()
                    {
                        CanPlayerEdit = false,
                        CanPlayerView = true,
                        FieldBoundTo = FieldBoundTo.Character,
                        FieldName = "Описание персонажа", //TODO[Localize]
                        FieldType = ProjectFieldType.Text,
                        IsActive = true,
                        IsPublic = true,
                        MandatoryStatus = MandatoryStatus.Optional,
                        IncludeInPrint = false,
                        ValidForNpc = true,
                        ProjectFieldId = -1,
                        Description = new MarkdownString(""),
                        MasterDescription = new MarkdownString(""),
                    };

                    project.ProjectFields.Add(project.Details.CharacterNameField);

                    project.ProjectFields.Add(project.Details.CharacterDescription);
                    break;
                case ProjectTypeDto.Convention:
                    project.Details.AutoAcceptClaims = true;
                    project.Details.EnableAccommodation = true;
                    project.Details.CharacterNameField = null;
                    project.Details.CharacterDescription = null;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public async Task AddCharacterGroup(int projectId,
            string name,
            bool isPublic,
            IReadOnlyCollection<int> parentCharacterGroupIds,
            string description,
            bool haveDirectSlotsForSave,
            int directSlotsForSave,
            int? responsibleMasterId)
        {
            var project = await ProjectRepository.GetProjectAsync(projectId);

            if (responsibleMasterId != null &&
                project.ProjectAcls.All(acl => acl.UserId != responsibleMasterId))
            {
                //TODO: Move this check into ChGroup validation
                throw new Exception("No such master");
            }

            project.RequestMasterAccess(CurrentUserId, acl => acl.CanEditRoles);
            project.EnsureProjectActive();

            Create(new CharacterGroup()
            {
                AvaiableDirectSlots = directSlotsForSave,
                HaveDirectSlots = haveDirectSlotsForSave,
                CharacterGroupName = Required(name),
                ParentCharacterGroupIds =
                    await ValidateCharacterGroupList(projectId,
                        Required(() => parentCharacterGroupIds)),
{'fraction_non_alphanumeric': 0.06780685842618986, 'fraction_numerical': 0.0005182689816014512, 'mean_word_length': 1.3931376601901613, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4214318', 'n_tokens_mistral': 2628, 'n_tokens_neox': 2490, 'n_words': 508}