public static async Task <bool> ResultAsync(MainRepository repo, SystemData system, DelayEffect delay, Func <uint, string, Task> logAsync)
        {
            var chara = await repo.Character.GetByIdAsync(delay.CharacterId);

            var type = (CharacterItemType)delay.TypeData;

            if (!chara.HasData)
            {
                return(false);
            }
            if (chara.Data.HasRemoved)
            {
                return(true);
            }

            var generateInfo = GenerateItemInfo.GetInfo(chara.Data, type);

            if (generateInfo == null)
            {
                return(false);
            }

            if (delay.IntAppearGameDateTime + generateInfo.Length <= system.IntGameDateTime)
            {
                var info = CharacterItemInfoes.Get(type);
                if (info.HasData)
                {
                    var item = new CharacterItem
                    {
                        Type        = type,
                        Status      = CharacterItemStatus.CharacterPending,
                        CharacterId = chara.Data.Id,
                        IntLastStatusChangedGameDate = system.IntGameDateTime,
                    };

                    if (info.Data.IsResource)
                    {
                        item.Resource = (ushort)(info.Data.DefaultResource + RandomService.Next((int)(generateInfo.ResourceAttribute(chara.Data) * 1.4f)));
                    }

                    await ItemService.GenerateItemAndSaveAsync(repo, item);

                    await ItemService.SetCharacterPendingAsync(repo, item, chara.Data);

                    if (info.Data.IsResource)
                    {
                        await logAsync(chara.Data.Id, $"アイテム {info.Data.Name} を生産しました。資源量: <num>{item.Resource}</num>");
                    }
                    else
                    {
                        await logAsync(chara.Data.Id, $"アイテム {info.Data.Name} を生産しました");
                    }

                    return(true);
                }
            }

            return(false);
        }
        public override async Task InputAsync(MainRepository repo, uint characterId, IEnumerable <GameDateTime> gameDates, params CharacterCommandParameter[] options)
        {
            var itemType = (CharacterItemType)options.FirstOrDefault(p => p.Type == 1).Or(ErrorCode.LackOfCommandParameter).NumberValue;

            var skills = await repo.Character.GetSkillsAsync(characterId);

            if (!skills.AnySkillEffects(CharacterSkillEffectType.GenerateItem, (int)itemType))
            {
                ErrorCode.NotSkillError.Throw();
            }

            var character = await repo.Character.GetByIdAsync(characterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

            var info = GenerateItemInfo.GetInfo(character, itemType);

            if (info == null)
            {
                ErrorCode.InvalidCommandParameter.Throw();
            }

            await repo.CharacterCommand.SetAsync(characterId, this.Type, gameDates, options);
        }
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var isRegularly = options.Any(p => p.Type == CharacterCommandParameterTypes.Regularly);

            var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1);

            if (itemTypeOptional == null || itemTypeOptional.NumberValue == null)
            {
                await game.CharacterLogAsync("アイテム生産のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>");

                return;
            }
            var itemType = (CharacterItemType)itemTypeOptional.NumberValue;

            var delays = await repo.DelayEffect.GetAllAsync();

            if (delays.Any(d => d.CharacterId == character.Id && d.Type == DelayEffectType.GenerateItem))
            {
                if (!isRegularly)
                {
                    await game.CharacterLogAsync($"アイテム生産しようとしましたが、複数のアイテムを同時に生産することはできません");
                }
                return;
            }

            var infoOptional = CharacterItemInfoes.Get(itemType);

            if (!infoOptional.HasData)
            {
                await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>");

                return;
            }
            var info = infoOptional.Data;

            var generateInfo = GenerateItemInfo.GetInfo(character, itemType);

            if (generateInfo == null)
            {
                await game.CharacterLogAsync("アイテム生産の情報が不正です。<emerge>管理者にお問い合わせください</emerge>");

                return;
            }

            var money = info.IsResource ? info.MoneyPerResource * info.DefaultResource / 16 : info.Money / 16;

            if (character.Money < money)
            {
                await game.CharacterLogAsync("アイテム生産しようとしましたが、金が足りません。<num>" + money + "</num> 必要です");

                return;
            }

            var townOptional = await repo.Town.GetByIdAsync(character.TownId);

            if (townOptional.HasData)
            {
                var country = await repo.Country.GetByIdAsync(character.CountryId);

                var town = townOptional.Data;
                if (town.CountryId != character.CountryId && country.HasData && !country.Data.HasOverthrown)
                {
                    await game.CharacterLogAsync($"<town>{town.Name}</town> でアイテム生産しようとしましたが、自国の都市ではありません");

                    return;
                }

                character.Money -= money;
                var delay = new DelayEffect
                {
                    CharacterId        = character.Id,
                    CountryId          = character.CountryId,
                    AppearGameDateTime = game.GameDateTime,
                    Type     = DelayEffectType.GenerateItem,
                    TypeData = (int)itemType,
                };
                await repo.DelayEffect.AddAsync(delay);

                await repo.SaveChangesAsync();

                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(delay), character.Id);

                var finish = GameDateTime.FromInt(game.GameDateTime.ToInt() + generateInfo.Length);
                generateInfo.AddExAttribute(character);
                if (!isRegularly)
                {
                    character.Contribution += generateInfo.Contribution;
                    character.SkillPoint++;
                }
                await game.CharacterLogAsync($"<town>{town.Name}</town> で <num>{money}</num> を投し、{info.Name} の生産を開始しました。結果は <num>{finish.Year}</num> 年 <num>{finish.Month}</num> 月に来ます");
            }
            else
            {
                await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>");
            }
        }