-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema eod_authentication
-- -----------------------------------------------------
-- 인증 데이터베이스
-- -----------------------------------------------------
-- Schema eod_game
-- -----------------------------------------------------
-- 게임 데이터베이스

-- -----------------------------------------------------
-- Schema eod_game
--
-- 게임 데이터베이스
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `eod_game` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
-- -----------------------------------------------------
-- Schema eod_log
-- -----------------------------------------------------
-- 로그 데이터베이스
-- -----------------------------------------------------
-- Schema eod_ranking
-- -----------------------------------------------------
-- 랭킹 데이터베이스
-- -----------------------------------------------------
-- Schema eod_community
-- -----------------------------------------------------
-- 커뮤니티 데이터베이스
-- -----------------------------------------------------
-- Schema eod_tool
-- -----------------------------------------------------
-- 서비스 관리도구용 데이터베이스
-- -----------------------------------------------------
-- Schema eod_configuration
-- -----------------------------------------------------
-- 서비스 설정 데이터베이스
-- -----------------------------------------------------
-- Schema eod_global
-- -----------------------------------------------------
-- 전역 서비스 관리 데이터베이스
USE `eod_game` ;

-- -----------------------------------------------------
-- Table `eod_game`.`table_player_character`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_player_character` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '캐릭터의 고유 식별 번호 ',
  `owner_user_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '소유자의 계정 ID',
  `character_class_type` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '캐릭터 직업 클래스 구분\n: eCharacterClass의 값과 같다.',
  `notice_state` INT(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '알림 상태\n\n - 플레이어 캐릭터에게 뭔가 변경 사항이 있음을 알릴 때 사용한다.\n\n - 새로운 편지(와 첨부물)가 도착했다거나, 친구 요청이 있거나, 길드 멤버 가입 요청이 있을 때 등을 말한다.\n\n -  비트 필드로 표현한다.\n : 비트 필드의 각 자릿수의 의미는 eNoticeState에서 정의하고 있다.',
  `title` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '캐릭터의 호칭',
  `title_color_key` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '호칭의 색상 키\n: eTextColorKey의 값과 같다.',
  `level` INT(11) NOT NULL DEFAULT '1' COMMENT '캐릭터의 현재 레벨',
  `experience` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '캐릭터의 현재 레벨에서의 경험치\n\n- 한 번 올랐던 레벨이 다시 내려가는(소위 \'렙따\') 기능이 없기 때문에, 굳이 누적된 총 경험치량을 가지고 있어야 할 필요가 없다고 본다.',
  `money_gameplay` INT(11) NOT NULL DEFAULT '0' COMMENT '이 캐릭터가 보유한 게임 플레이 화폐',
  `admission` INT(11) NOT NULL DEFAULT '0' COMMENT '캐릭터가 보유하고 있는, 스테이지에 입장할 때 소모하는 자원',
  `admission_recharge_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지 입장권의 재생성을 시작한 시간\n\n- 캐릭터의 레벨에 따라 주어진 최대 재생성 수량보다 현재의 입장권 개수가 모자하는 시점에 기록한다.\n- 현재 입장권 보유 수량이 캐릭터의 최대 재생성 수량보다 같거나 크면, 시간을 세지 않는 의미에서, 시간 값을 DateTime 형의 최소 값으로 수정한다. (이걸 무효값으로 간주한다.)',
  `rift_keystone` INT(11) NOT NULL DEFAULT '0' COMMENT '균열석\n\n- 균열 던전 입장권임',
  `money_ruby` INT(11) NOT NULL DEFAULT '0' COMMENT '루비 화폐의 양',
  `stage_effect_tickets` INT(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '현재 스테이지를 플레이 할 때 적용한 부여효과들의 목록\n\n- 부여효과들은 일종의 티켓 종류의 재화로 취급한다. \n: 타입은 eEquipType.ItemIncreaseTicket, eEquipType.ExpIncreaseTicket, eEquipType.GoldIncreaseTicket 등이다.\n\n- 여러 종류의 부여효과들을 한 번에 부여할 수 있고, 각 부여효과들은 한 번에 재화를 1 단위로 소모한다.\n: 따라서, 효율적인 저장과 처리를 위하여 스테이지 진입과 관련한 부여효과들은 비트필드로써 처리한다.\n\n- 세부적인 비트필드의 값은 (eStageEnchantedEffect 열거형의 값을 참고할 것)\n\n 0 = eStageEnchantedEffect.None (아무 것도 없음)\n 1 << 1 = eStageEnchantedEffect.IncreaseItem (아이템 보상 증가)\n 1 << 2 = eStageEnchantedEffect.IncreaseExperience (경험치 보상 증가)\n 1 << 3 = eStageEnchantedEffect.IncreaseMoneyGamePlay (게임 플레이 화폐 보상 증가)',
  `equipped_potion_gtc` INT(11) NOT NULL DEFAULT '0' COMMENT '장착한 물약 아이템의 타입 식별 코드(GTC)',
  `item_inventory_extension_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '캐릭터의 아이템 인벤토리 확장 단계\n\n- 캐릭터의 아이템 인벤토리는 어느 정도의 기본적인 슬롯 개수가 있다.\n\n- 그리고 구매를 통해 이 공간을 더 확장할 수 있다.\n\n- 여기서는 그렇게 구매를 통해서 확장한 공간들에 대한 단계 값을 가지고 있다.\n: 각 단계들이 실제로 몇 개의 아이템 인벤토리 슬롯을 늘려주는지는 게임 데이터에 달려 있다.',
  `skill_point_by_purchase` INT(11) NOT NULL DEFAULT '0' COMMENT '구매한 스킬 포인트\n\n- 스킬 포인트를 캐릭터의 레벨에 의해 제공하는 기본 스킬 포인트와, 직접 구매하는 스킬 포인트가 있다.\n\n- 두 스킬 포인트의 용도는 똑같다.\n: 스킬을 강화하는데 사용한다.\n\n- 스킬을 강화할 때는 무조건 캐릭터 레벨에 의해 제공하는 기본 스킬 포인트부터 소진한 뒤에, 구매한 스킬 포인트를 소진한다.\n\n- 구매한 스킬 포인트는 해당 플레이어의 모든 캐릭터에 공통으로 적용한다.',
  `skill_point_reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '이 캐릭터가 스킬을 초기화한 횟수\n\n- 스킬 강화 단계의 초기화는 스킬 구분 없이 모든 스킬에 대해 일괄적으로 이루어진다.\n: 스킬 강화단계 초기화를 수행하면, 일시에 모든 스킬의 모든 스킬 포인트를 회수한다.\n\n- 아마도, 기획에 의해 스킬 강화 단계의 초기화를 한 횟수만큼 다음 번 초기화 비용이 비싸질 것이다.',
  `last_played_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '마지막으로 플레이 한 일시',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`),
  INDEX `owner_user_id_character_class_type` (`owner_user_id` ASC, `character_class_type` ASC),
  INDEX `idx_table_player_character_owner_user_id_level` (`owner_user_id` ASC, `level` ASC))
ENGINE = InnoDB
COMMENT = '플레이어 캐릭터 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_equipment_item`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_equipment_item` (
  `item_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '아이템의 고유 번호 \n\n- 생성한 아이템마다 고유한 번호가 붙어야 한다. \n : 부가 옵션이 무작위한 조합으로 붙을 수 있기 때문임.',
  `item_code` INT(11) NOT NULL DEFAULT '0' COMMENT '아이템의 종류 식별 코드',
  `owner_character_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '아이템 소유자 캐릭터의 ID',
  `state` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '아이템의 상태\n\n- eItemState의 값과 같다.',
  `fixed_options` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '이 아이템에 부여된 고정 능력 옵션들\n\n- 아이템이 생성될 때 부여되는 옵션 중에서, 아이템에 고정적으로 부여되는 옵션\n\n- 이 옵션들은 아이템이 승급하더라도, 그 \'종류\'가 바뀌지 않는다.\n: 능력의 강함은 바뀔 수 있다.\n\n- JSON 형식의 문자열로 표현한다.\n\n- 각 옵션들을 의사코드로 표현하면 아래와 같은 방식이다.\n{\n    type_code  : 10000\n    parameters : \n    {\n        $(parameter1) : $(value), \n        $(parameter2) : $(value), \n        $(parameter3) : $(value), \n        $(parameter4) : $(value), \n       ....\n    }\n}',
  `random_options` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '이 아이템에 부여된 무작위 능력 옵션들\n\n- 아이템이 생성될 때 무작위로 부여되는 옵션들\n: 단, 완전한 무작위는 아니고, 보상 체계에 따라 그 범위와 확률이 정해진다.\n\n- 아이템이 승급하는 경우, 무작위 능력 옵션들은 전체가 교체되는 방식이다.\n: 우연히 같은 종류의 옵션으로 다시 부여될 수도 있다.\n\n- JSON 형식의 문자열로 표현한다.\n\n- 각 옵션들을 의사코드로 표현하면 아래와 같은 방식이다.\n{\n    type_code  : 10000\n    parameters : \n    {\n        $(parameter1) : $(value), \n        $(parameter2) : $(value), \n        $(parameter3) : $(value), \n        $(parameter4) : $(value), \n       ....\n    }\n}',
  `option_factor` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '아이템 능력 옵션에 적용할 계수\n: 계수를 실제로 어떻게 적용할지는 애플리케이션의 구현 여부에 달려 있다.',
  `enhance_level` INT(11) NOT NULL DEFAULT '0' COMMENT '아이템의 강화 점수\n: 이것으로 아이템의 강화 레벨을 계산할 수 있다.\n 만약, 강화 단계가 즉각적으로 올라가는 방식이라면, 점수가 곧 레벨이 되면 된다.',
  `runestone_socket_size` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '이 아이템에 룬스톤 소켓이 몇 개 있는지 나타낸다.\n\n- 룬스톤 소켓의 개수만큼 룬스톤 옵션을 부여할 수 있다.',
  `runestone_socket1` INT(11) NOT NULL DEFAULT '0' COMMENT '1번째 룬스톤 소켓',
  `runestone_socket2` INT(11) NOT NULL DEFAULT '0' COMMENT '2번째 룬스톤 소켓',
  `locked` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '아이템에 잠금을 설정했는 여부\n\n- 잠금 상태인 아이템은 분해 등으로 아이템을 파괴하거나 변경하는 행위가 불가능하다.',
  `option_change_state` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마법부여 진행 상태\n\n0 : 미진행\n1 : 진행',
  `option_change_target` INT(11) NOT NULL DEFAULT '-1' COMMENT '교체할 옵션의 인덱스 (한번 정해지면 변경할 수 없다)\n\n- 무작위 옵션 목록의 인덱스로 표현한다.\n: 고정 옵션은 변경할 수 없다.',
  `option_change_nominates` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '마법부여 진행 시 추첨해서 나온 옵션 목록 임시저장',
  `option_change_count` INT(11) NOT NULL DEFAULT '0' COMMENT '이 아이템의 옵션을 몇 번 교체했는지 여부\n\n- 기획에 의해 아이템 옵션을 여러 번 교체하면, 교체할 때마다 다음 번 교체 비용이 상승해야 하기 때문이다.\n\n- 교체 횟수는  option_change_type에 관계 없이 동일하게 적용한다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  `creation_datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`item_id`),
  INDEX `owner_character_id` (`owner_character_id` ASC))
ENGINE = InnoDB
COMMENT = '캐릭터가 보유한 장착 아이템 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_skill`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_skill` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '스킬을 소유한 캐릭터의 ID',
  `skill_code` INT(11) NOT NULL COMMENT '스킬 종류의 식별 코드',
  `enhance_level` INT(11) NOT NULL DEFAULT '0' COMMENT '스킬의 강화 점수\n\n- 현재 강화 점수가 있다면, 스킬의 현재 강화 레벨을 계산할 수 있다.\n\n- 현재는 강화 점수 1점이 곧 스킬 1레벨이다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `skill_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 스킬 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_player`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_player` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '사용자 계정 ID',
  `authentication_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '사용자의 인증 번호\n\n- 모든 사용자들은 계정에 접근할 때마다 인증 번호를 부여 받는다.\n- 인증 번호는 인증 서버 및 DB에서만 발급한다.\n- 게임 서버에 저장하는 인증 번호는 그냥 해당 사용자가 로그인한 게 맞는지 확인하는 용도로만 사용한다.\n: 즉, 계정활동에 의해 인증 번호가 바뀌었으면, 무조건 인증 DB의 인증 번호가 유효한 것이다. ',
  `nickname` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '사용자' /* comment truncated */ /*계정 별명

- 잠정적으로 보통 별명은 보통 최대 16글자까지 할당한다고 가정한다.

- 그래서, 이름에 16 × 3 = 48 바이트가 필요하다.

- 삭제한 계정의 경우, 다른 사용자가 이름을 사용할 수 있도록 하기 위해, 삭제한 계정의 이름에 추가적인 문자열을 넣어서 바꿔야 한다.
: 이 때, 바꾸는 이름도 전체 DB에서 유일해야 하므로, 대개 user_id를 넣어서 바꾸게 된다.
  user_id는 64비트 부호 없는 정수이기 때문에 20자리까지 나오는 수이다. 그러므로 20바이트는 추가로 필요하다. 

-  거기에 추가적으로 더 붙어야 하는 여유 공간을 생각하면 총 48 + 20 + 28 = 96바이트가 적당한 것 같다.
: 이 정도면 별명 길이의 한계가 20글자로 더 길어져야 한다고 해도 여유 공간상 크게 문제 없다고 본다.

- eod_authentication.table_account_user.nickname으로부터 받아와서 저장하기 위해 존재한다.
: 이렇게 하는 이유는, 게임 DB는 가장 많은 IO가 몰리는 곳이기 때문에, 플레이어들을 분산해서 저장할 것이기 때문이다.
  그런데 계정 별명의 유효성 검사는 인증 서버 단계에서 하기 때문에(전체 플레이어들을 검사해야 하므로) 문제가 생긴다.
  계정 별명은 게임 내부에서 상당히 자주 사용하는 요소인데, 이거 알아내려고 게임 플레이 도중 인증 DB에 자주 접근을 해야 하는 상황이면 게임 DB를 분산하는 의미가 퇴색한다.
  그래서 공간 낭비가 됨을 알면서도, 계정 별명이라든가, 계정 인증 번호는 게임 DB에 따로 저장을 해두는 것이다. 인증 DB에 접근하는 경우를 최소화하기 위해서다.*/,
  `notice_state` INT(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '알림 상태\n\n - 플레이어에게 뭔가 변경 사항이 있음을 알릴 때 사용한다.\n\n - 새로운 편지(와 첨부물)가 도착했다거나, 친구 요청이 있거나, 길드 멤버 가입 요청이 있을 때 등을 말한다.\n\n -  비트 필드로 표현한다.\n : 비트 필드의 각 자릿수의 의미는 eNoticeState에서 정의하고 있다.',
  `vip_level` TINYINT(4) NOT NULL DEFAULT '0' COMMENT 'VIP 등급\n\n- VIP 등급을 별도로 저장하기로 한다.\n\n- 이렇게 하는 이유는, 우선 VIP 레벨을 한 번 달성하게 하면, 이를 변동시킬 수는 없기 때문이다.\n: VIP 포인트만 저장하는 경우에는, 포인트의 분배 조정에 따라 VIP 레벨이 변동될 수도 있는 여지가 있다. \n  그러나 과금과 직결되는 VIP 레벨 요소를 이렇게 다루는 것은 비즈니스 상 매우 어렵다고 본다. (어쨌든, 이건 은행 신용 등급같은 게 아니니까...)',
  `vip_point` INT(11) NOT NULL DEFAULT '0' COMMENT '현재 VIP레벨부터 다음 VIP 레벨까지 누적한 VIP 포인트',
  `guardian_level` INT(11) NOT NULL DEFAULT '0' COMMENT '수호자 레벨\n\n- 기본적으로 50레벨에 도달하지 않은 캐릭터는 수호자 레벨이 0으로 설정\n- 50 레벨 캐릭터가 만들어진 이후에 수호자 레벨이 1로 설정됨',
  `guardian_experience` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '현재 수호자 레벨 -> 다음 수호자 레벨 구간에서 현재까지 획득한 수호자 경험치',
  `guardian_stone_enhance_point` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '현재 가지고 있는 수호석 포인트\n\n- 수호석 포인트는 아무 수호석에게나 부여하여, 수호석의 강화 레벨을 향상시킬 수 있다.\n\n- 수호석 포인트는 초월 던전에서 획득할 수 있다.',
  `money_gamecash_by_bonus` INT(11) NOT NULL DEFAULT '0' COMMENT '이 캐릭터가 보유하고 있는 과금 화폐 중에서, 플레이어가 결제하지 않고 얻은 과금 화폐의 양\n\n다음과 같은 경우에 해당한다.\n\n- 게임 플레이 도중에 보상으로 얻은 경우\n\n- 게임 운영 서비스 차원에서 보상으로 주어진 경우\n\n- 과금 화폐는 구매한 플레이어 계정의 모든 캐릭터가 이용할 수 있다.\n: 단, 이는 공유의 개념이지, 각 캐릭터마다 별도로 책정된다는 의미가 아니다.',
  `money_gamecash_by_purchase` INT(11) NOT NULL DEFAULT '0' COMMENT '보유하고 있는 과금 화폐 중에서, 직접 결제해서 구매한 과금 화폐의 양\n\n- 과금 화폐는 구매한 플레이어 계정의 모든 캐릭터가 이용할 수 있다.\n: 단, 이는 공유의 개념이지, 각 캐릭터마다 별도로 책정된다는 의미가 아니다.\n\n- 사용자의 과금량을 측정하는 용도로 사용하기 때문에, 반드시 직접 과금한 화폐와 아닌 화폐를 구분할 수 있어야 한다.\n\n- 다른 재화들은 사용자가 직접 결제하여 구매하는 방식이 아니므로 이런 구분은 필요 없다.\n: 다른 재화들은 이 화폐를 이용해서 구매하게 되어 있다.',
  `friendship_point` INT(11) NOT NULL DEFAULT '0' COMMENT '우정점수',
  `remain_monthly_reward_count` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '월 정액 상품을 구매했을 때, 남은 일별 보상 횟수',
  `current_bought_premium_package` INT(11) NOT NULL DEFAULT '0' COMMENT '현재 프리미엄 패키지를 구매한 횟수',
  `deletable_friend_count` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '친구를 삭제할 수 있는 남은 횟수',
  `last_accessed_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '마지막으로 접속한 일시',
  `last_played_character` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이한 캐릭터\n\n- 캐릭터를 선택해서 게임에 진입한다면, 이 값을 선택한 캐릭터의 코드 번호로 업데이트한다.\n\n- 슬롯 번호가 아니다!',
  `enable_to_change_nickname` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '계정 별명의 변경 권한\n\n- 계정 이름 변경 권한은 1회씩만 활성화할 수 있다.\n: 이름 변경 권한을 다시 얻기 위해서는, 먼저 이름 변경을 해서 횟수를 0이 되게 소비를 해야 한다.',
  `representative_character` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '플레이어를 대표할 캐릭터의 ID\n: 플레이어 자신이 소유한 캐릭터의 ID여야 한다.',
  `enable_to_change_representative_character_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '다음 차례에 대표 캐릭터를 교체할 수 있는 일시',
  `joined_guild_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '가입한 길드의 ID',
  `guild_coin` INT(11) NOT NULL DEFAULT '0' COMMENT '길드 코인',
  `mileage` INT(11) NOT NULL DEFAULT '0' COMMENT '현재 소유하고 있는 마일리지의 양',
  `cumulative_mileage` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '누적한 마일리지의 양',
  `is_completed_tutorial` TINYINT(1) NOT NULL DEFAULT '0',
  `enable_to_guild_activity_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '길드 활동(길드 창설, 길드 가입)을 다시 시작할 수 있는 일시',
  `guild_attendance_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '마지막으로 길드에 출석한 일시',
  `related_account_facebook` VARCHAR(30) NOT NULL DEFAULT '' COMMENT '연동된 Facebook 계정\n\n- Facebook 계정은 16자리의 숫자로 이루어져 있다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`),
  UNIQUE INDEX `nickname_UNIQUE` (`nickname` ASC),
  UNIQUE INDEX `authentication_number_UNIQUE` (`authentication_number` ASC),
  INDEX `related_account_facebook_INDEX` (`related_account_facebook` ASC),
  INDEX `idx_table_player_user_id_guardian_level` (`user_id` ASC, `guardian_level` ASC))
ENGINE = InnoDB
COMMENT = '플레이어 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_avatar_item`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_avatar_item` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의  ID',
  `avatar_item_code` INT(11) NOT NULL COMMENT '아바타 아이템의 종류를 식별하는 코드',
  `enhance_level` INT(11) NOT NULL DEFAULT 0,
  `option_division` INT(11) NOT NULL DEFAULT 0,
  `option_ability` INT(11) NOT NULL DEFAULT 0,
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `avatar_item_code`))
ENGINE = InnoDB
COMMENT = '캐릭터의 아바타 아이템 보유 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_normal_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_normal_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '스테이지의 액트 번호',
  `stage_number_in_act` TINYINT(4) NOT NULL COMMENT '스테이지 액트에서의 스테이지 번호',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증번호',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '캐릭터가 해당 스테이지를 플레이할 수 있는 횟수를 초기화한 일시',
  PRIMARY KEY (`character_id`, `act_number`, `stage_number_in_act`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 일반 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_servant`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_servant` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `servant_code` INT(11) NOT NULL COMMENT '조력자 캐릭터의 코드\n\n- 각 캐릭터들은 각 조력자들을 하나씩만 소유할 수 있다.',
  `grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '현재 조력자 등급\n: TableEnum의 eSummonGrade 열거형의 값과 같다.',
  `level` INT(11) NOT NULL DEFAULT '1' COMMENT '조력자 캐릭터의 레',
  `experience` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '조력자 캐릭터의 현재 레벨에서의 경험치',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `servant_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 보유한 조력자 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_worth`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_worth` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `worth_code` INT(11) NOT NULL COMMENT '조력자 캐릭터의 종류 식별 코드',
  `amount` INT(11) NOT NULL DEFAULT '0' COMMENT '조력자 캐릭터 조각의 개수',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `worth_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 재화 보유 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_guardian_stone`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_guardian_stone` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `guardian_stone_code` INT(11) NOT NULL COMMENT '수호석의 종류 식별 코드',
  `state` TINYINT(4) NULL DEFAULT '0' COMMENT '수호석의 상태\n: eItemState의 값과 같다.',
  `enhance_level` INT(11) NOT NULL DEFAULT '0' COMMENT '강화레벨\n\n- 최초에는 0 단계이다.\n: 강화를 해야 1레벨이 되는 방식임.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `guardian_stone_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별  보유한 수호석 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_elite_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_elite_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '스테이지의 액트 번호',
  `stage_number_in_act` TINYINT(4) NOT NULL COMMENT '스테이지 액트에서의 스테이지 번호',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증번호',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '해당 스테이지를 플레이할 수 있는 남은 횟수',
  `reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '캐릭터가 해당 스테이지를 플레이할 수 있는 횟수를 초기화한 횟수',
  `reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '캐릭터가 해당 스테이지를 플레이할 수 있는 횟수를 초기화한 일시',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `act_number`, `stage_number_in_act`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 정예 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_rift_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_rift_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `stage_grade` INT(11) NOT NULL COMMENT '스테이지의 단계',
  `party_play_mode` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '파티 플레이 모드\n: ePartyPlayMode의 값과 같다.',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증 번호\n: 파티 플레이인 경우에만 검사한다.',
  `completed_wave_index` TINYINT(4) NOT NULL DEFAULT '-1' COMMENT '이 단계에서 최대 완료한 웨이브의 인덱스',
  `now_cleared_wave_index` TINYINT(4) NOT NULL DEFAULT '-1' COMMENT '현재 완료한 웨이브의 인덱스',
  `wave_auth_number` INT(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '웨이브 인증번호\n\n - 웨이브를 시작할 때마다 요청한 캐릭터에게 발급한다.\n\n - 0은 무효값이다.\n\n - 각 캐릭터마다 고유하게 사용한다. (캐릭터 간에는 겹치는 번호가 있을 수 있다.)\n\n - 이 번호를 올바르게 전달하지 않으면, 다음 웨이브 진입 요청을 거부한다.',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `stage_grade`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 균열 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_transcendence_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_transcendence_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `stage_grade` INT(11) NOT NULL COMMENT '대상 스테이지의 등급',
  `party_play_mode` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '파티 플레이 모드\n: ePartyPlayMode의 값과 같다.',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증 번호\n: 파티 플레이인 경우에만 검사한다.',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `revive_instantly_count` INT(11) NULL DEFAULT '0' COMMENT '이 초월 스테이지에서 즉시 부활한 횟수',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `stage_grade`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 초월 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_weekly_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_weekly_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `day_of_week` TINYINT(4) NOT NULL COMMENT '요일 타입\n\n- .NET Framework의 System.DayOfWeek의 값을 따른다.\n\n- 즉, 다음과 같다.\n\n Sunday = 0,\n  Monday = 1,\n  Tuesday = 2,\n  Wednesday = 3,\n  Thursday = 4,\n  Friday = 5,\n  Saturday = 6',
  `stage_grade` INT(11) NOT NULL COMMENT '대상 스테이지의 등급',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `day_of_week`, `stage_grade`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 요일 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_normal_act_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_normal_act_record` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '액트 번호',
  `rewarded_clear_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '현재 액트에 대해 보상을 받은 완료 등급 개수\n\n- 각 액트들은 스테이지를 완료한 등급을 더하여, 그 수가 일정한 수치에 다다르면 보상을 지급한다.\n\n- 다만, 보상의 지급을 미룰 수도 있어야 하는데, 그 때문에 현재까지 보상을 받은 등급 개수를 저장해야 할 필요가 있다.\n: 이 필드가 그 값을 저장하는 역할을 한다.',
  `repeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '현재까지 누적된 반복횟수\n\n- 반복횟수는 보상을 받을 때마다, 보상을 지급하는 반복 횟수의 단위만큼 차감한다.\n: 이는 이 필드의 값이 0이 되거나, 혹은 더 이상 보상을 지급할 수 있는 반복 횟수 단위에 미치지 못하게 될 때까지 반복한다.',
  `is_rewarded_first_repetition` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '첫 번째 반복인지 여부\n\n- 반복 보상을 처음으로 받는 경우와, 그 이후에 받는 경우의 보상 지급 방식이 다르다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신 일시',
  PRIMARY KEY (`character_id`, `act_number`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 일반 스테이지의 액트 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_elite_act_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_elite_act_record` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '액트 번호',
  `rewarded_clear_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '현재 액트에 대해 보상을 받은 완료 등급 개수\n\n- 각 액트들은 스테이지를 완료한 등급을 더하여, 그 수가 일정한 수치에 다다르면 보상을 지급한다.\n\n- 다만, 보상의 지급을 미룰 수도 있어야 하는데, 그 때문에 현재까지 보상을 받은 등급 개수를 저장해야 할 필요가 있다.\n: 이 필드가 그 값을 저장하는 역할을 한다.',
  `repeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '현재까지 누적된 반복횟수\n\n- 반복횟수는 보상을 받을 때마다, 보상을 지급하는 반복 횟수의 단위만큼 차감한다.\n: 이는 이 필드의 값이 0이 되거나, 혹은 더 이상 보상을 지급할 수 있는 반복 횟수 단위에 미치지 못하게 될 때까지 반복한다.',
  `is_rewarded_first_repetition` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '첫 번째 반복인지 여부\n\n- 반복 보상을 처음으로 받는 경우와, 그 이후에 받는 경우의 보상 지급 방식이 다르다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신 일시',
  PRIMARY KEY (`character_id`, `act_number`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 정예 스테이지의 액트 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_record` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `call_friend_remain_count` INT(11) NOT NULL DEFAULT '0' COMMENT '스테이지 내에서 친구 캐릭터를 소환할 수 있는 남은 횟수',
  `call_friend_count_reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지 내에서 친구 호출하는 횟수를 갱신한 일시',
  `normal_last_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트의 번호(일반 모드)',
  `normal_last_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트 내 스테이지의 번호(일반 모드)',
  `normal_far_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트의 번호(일반 모드)',
  `normal_far_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트 내 스테이지의 번호(일반 모드)',
  `elite_last_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트의 번호(정예 모드)',
  `elite_last_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트 내 스테이지의 번호(정예 모드)',
  `elite_far_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트의 번호(정예 모드)',
  `elite_far_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트 내 스테이지의 번호(정예 모드)',
  `rift_last_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막에 플레이 한 균열 던전의 단계',
  `rift_far_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 균열 던전의 단계',
  `rift_remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '균열 모드 스테이지의 남은 플레이 횟수',
  `rift_play_count_max` INT(11) NOT NULL DEFAULT '0' COMMENT '균열 모드 최대 플레이 횟수',
  `rift_reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '균열 모드 플레이 횟수 제한을 초기화한 횟수',
  `rift_reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '균열 모드 스테이지의 플레이 횟수를 초기화한 일시',
  `transcendence_last_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 초월 던전의 단계',
  `transcendence_far_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 초월 던전의 단계',
  `weekly_last_played_stage_grade_sunday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(일요일)',
  `weekly_far_played_stage_grade_sunday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(일요일)',
  `weekly_last_played_stage_grade_monday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(월요일)',
  `weekly_far_played_stage_grade_monday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(월요일)',
  `weekly_last_played_stage_grade_tuesday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(화요일)',
  `weekly_far_played_stage_grade_tuesday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(화요일)',
  `weekly_last_played_stage_grade_wednesday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(수요일)',
  `weekly_far_played_stage_grade_wednesday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(수요일)',
  `weekly_last_played_stage_grade_thursday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(목요일)',
  `weekly_far_played_stage_grade_thursday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(목요일)',
  `weekly_last_played_stage_grade_friday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(금요일)',
  `weekly_far_played_stage_grade_friday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(금요일)',
  `weekly_last_played_stage_grade_saturday` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 요일 던전의 단계(토요일)',
  `weekly_far_played_stage_grade_saturday` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 요일 던전의 단계(토요일)',
  `weekly_remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '주간 모드 스테이지의 남은 플레이 횟수',
  `weekly_play_count_max` INT(11) NOT NULL DEFAULT '0' COMMENT '요일 던전 최대 플레이 횟수',
  `weekly_reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '주간 모드 플레이 횟수 제한을 초기화한 횟수',
  `weekly_reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '주간 모드 스테이지의 플레이 횟수를 초기화한 일시',
  `weekly_repeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '주간 던전의 반복 횟수',
  `is_rewarded_first_repetition_weekly` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '첫 번째 반복인지 여부(요일 모드)\n\n - 반복 보상을 처음으로 받는 경우와, 그 이후에 받는 경우의 보상 지급 방식이 다르다.',
  `west_last_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트의 번호(서부 지역 모드)',
  `west_last_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '마지막으로 플레이 한 액트 내 스테이지의 번호(서부 지역 모드)',
  `west_far_played_act_number` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트의 번호(서부 지역 모드)',
  `west_far_played_stage_number_in_act` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 액트 내 스테이지의 번호(서부 지역 모드)',
  `guardian_raid_last_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '마지막에 플레이 한 수호 레이드 던전의 단계',
  `guardian_raid_far_played_stage_grade` INT(11) NOT NULL DEFAULT '0' COMMENT '가장 멀리까지 도달한 수호 레이드 던전의 단계',
  `guardian_raid_remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '수호 레이드 모드 스테이지의 남은 플레이 횟수',
  `guardian_raid_play_count_max` INT(11) NOT NULL DEFAULT '0' COMMENT '수호 레이드 모드 최대 플레이 횟수',
  `guardian_raid_reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '수호 레이드 모드 플레이 횟수 제한을 초기화한 횟수',
  `guardian_raid_reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '수호 레이드 모드 스테이지의 플레이 횟수를 초기화한 일시',
  `guardian_raid_repeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '수호 레이드의 반복 횟수',
  `is_rewarded_first_repetition_guardian_raid` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '첫 번째 반복인지 여부(수호 레이드 모드)\n\n - 반복 보상을 처음으로 받는 경우와, 그 이후에 받는 경우의 보상 지급 방식이 다르다.',
  `arena_async_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 인증번호\n\n- 결투장에 입장할 때마다 바뀐다.\n\n- 클라이언트는 결투장에 입장할 때, 매칭 서버에 이 인증번호를 제출해야만 한다.\n\n- 결투장 대전의 결과로 보상을 받을 때, 이 인증번호로 보상 수령 여부를 검증한다. (검증 주체는 매칭 서버)',
  `arena_async_start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '결투장(비동기식)의 시작 일시',
  `arena_async_remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 오늘 남은 플레이 횟수',
  `arena_async_play_count_max` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식) 최대 플레이 횟수',
  `arena_async_reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 플레이 횟수제한을 초기화한 횟수',
  `arena_async_reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '결투장(비동기식)의 플레이 횟수를 초기화한 일시',
  `arena_async_straight_win_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 현재 연속 승리 횟수\n: 한 번이라도 패하면 0으로 되돌아감.',
  `arena_async_straight_defeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 현재 연속 패배 횟수\n: 한 번이라도 승리하면 0으로 되돌아감.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신 일시',
  PRIMARY KEY (`character_id`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 스테이지 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_equipment_item_equipped`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_equipment_item_equipped` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL,
  `equip_slot_type` TINYINT(4) NOT NULL COMMENT '장착하고 있는 위치\n\n  0 = 무기\n  1 = 머리\n  2 = 상의\n  3 = 하의\n  4 = 장갑\n  5 = 신발\n  6 = 목걸이\n  7 = 반지\n\n  -1 = 없음. (장착할 수 없는, 인벤토리에서만 존재해야 하는 아이템)',
  `item_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '아이템의 ID',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일',
  PRIMARY KEY (`character_id`, `equip_slot_type`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 장착 아이템의 장착 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_avatar_item_equipped`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_avatar_item_equipped` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `equip_slot_type` TINYINT(4) NOT NULL COMMENT '아바타 아이템을 장착한 부위\n\neEquipType과 같다.\n\n  0 = None - > 장착하지 않았다는 뜻이다.\n  33 = AvatarWeapon -> 아바타 무기\n  34 = AvatarHead -> 아바타 머리\n  35 = AvatarBody -> 아바타 몸통\n  36 = AvatarSpecial -> 아바타 특수부위 (캐릭터 클래스마다 다름)',
  `avatar_item_code` INT(11) NOT NULL DEFAULT '0',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `equip_slot_type`))
ENGINE = InnoDB
COMMENT = '캐릭터의 아바타 아이템 장착 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_skill_equipped`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_skill_equipped` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `equip_lane` TINYINT(4) NOT NULL COMMENT '스킬의 장착 레인\n\n- 스킬의 성격에 따라 장착할 수 있는 레인을 나눈다.\n\n- 각 레인은 다음과 같다.\n\n  0 = 장착하지 않음.\n  1 = 액티브 스킬\n  2 = 패시브 스킬\n  3 = 연계 스킬\n  4 = 수호자 스킬',
  `lane_index` TINYINT(4) NOT NULL COMMENT '각 레인에서의 인덱스\n\n- 캐릭터가 스킬들을 이 순서대로 장착했다는 의미이다.\n\n- 인덱스는 0부터 시작한다.\n: 일반적인 배열과 똑같이 취급한다.\n\n- 인덱스 무효값은 -1이다.',
  `skill_code` INT(11) NOT NULL DEFAULT '0',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00',
  PRIMARY KEY (`character_id`, `equip_lane`, `lane_index`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 스킬 장착 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_guardian_stone_equipped`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_guardian_stone_equipped` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `equip_slot_index` TINYINT(4) NOT NULL COMMENT '장착한 슬롯의 인덱스\n\n- 0부터 시작한다.\n\n- 0보다 작은 숫자는 무효값으로 간주하며, 장착하지 않은 상태라는 의미이다.',
  `guardian_stone_code` INT(11) NOT NULL DEFAULT '0' COMMENT '수호석의 종류 식별 코드',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `equip_slot_index`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 수호석 장착 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_servant_equipped`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_servant_equipped` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '소유자 캐릭터의 ID',
  `equip_slot_index` TINYINT(4) NOT NULL COMMENT '장착한 슬롯의 인덱스\n\n- 0부터 시작한다.\n\n- 0보다 작은 수는 무효값이며, 장착하지 않은 상태임을 나타낸다.',
  `servant_code` INT(11) NOT NULL DEFAULT '0' COMMENT '조력자 캐릭터의 코드\n\n- 각 캐릭터들은 각 조력자들을 하나씩만 소유할 수 있다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `equip_slot_index`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 조력자 장착 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_attendance_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_attendance_record` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL,
  `is_exist_basic_reward` TINYINT(1) NOT NULL DEFAULT '0',
  `attendance_basic_count` TINYINT(4) NOT NULL DEFAULT '0',
  `is_exist_continue_reward` TINYINT(1) NOT NULL DEFAULT '0',
  `attendance_continue_count` TINYINT(4) NOT NULL DEFAULT '0',
  `is_exist_event_reward` TINYINT(1) NOT NULL DEFAULT '0',
  `attendance_event_count` TINYINT(4) NOT NULL DEFAULT '0',
  `is_come_back` TINYINT(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`user_id`))
ENGINE = InnoDB
COMMENT = '플레이어 별 출석 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_achievement`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_achievement` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어의 사용자 ID\n\n- 업적은 플레이어 단위로 작동한다.',
  `character_id` BIGINT(20) UNSIGNED NOT NULL,
  `achievement_code` INT(11) NOT NULL COMMENT '업적의 타입 식별 코드\n\n- GTC 값이다.',
  `state` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '업적의 수행 상태\n: eAchievementState의 값과 같다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00',
  PRIMARY KEY (`user_id`, `character_id`, `achievement_code`))
ENGINE = InnoDB
COMMENT = '플레이어, 캐릭터 별 업적의 달성 상태 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_mission`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_mission` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `mission_code` INT(11) NOT NULL COMMENT '미션의 타입 식별 코드\n\n- GTC 값이다.',
  `state` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '미션의 수행 상태\n\n 0 = None (아무 상태도 아님. 달성 여부를 점검하는 대상이 아니다.)\n 1 = Activated (활설화됨)\n 2 = Success (목표 달성에 성공한 상태. 서버 상에서는 보상 지급을 기다리는 상태.)\n 3 = Failed (목표 달성에 실패한 상태.)\n 4 = Completed (미션 목표가 성공 / 실패하고 보상 지급까지 모두 완료한 상태)',
  `record` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '이 미션과 관련하여 현재까지 달성한 값\n\n- 현재는 잠정적으로 하나의 숫자 값 형식으로 수렴하도록 디자인하고 있다.\n\n- 숫자 자체는 정수 / 실수 여부와 한계값을 명확히 알 수 없으므로, 가장 범용적으로 사용할 수 있는 값 형식을 사용한다.',
  `expired_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '현재 미션의 달성 상태를 파기할 일시\n: 이 시간이 지나면, 미션을 초기화한다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `mission_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 미션 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_quest`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_quest` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `group_id` INT(11) NOT NULL,
  `general_type_code` INT(11) NOT NULL DEFAULT '0' COMMENT '퀘스트 타입 식별 코드\n\n- GTC 값이다.',
  `condition_count` INT(11) NOT NULL DEFAULT '-1' COMMENT '퀘스트 수행 상태\n\n 0 = None (아무 상태도 아님. 달성 여부를 점검하는 대상이 아니다.)\n 1 = Activated (활설화됨)\n 2 = Success (목표 달성에 성공한 상태. 서버 상에서는 보상 지급을 기다리는 상태.)\n 3 = Failed (목표 달성에 실패한 상태.)\n 4 = Completed (미션 목표가 성공 / 실패하고 보상 지급까지 모두 완료한 상태)',
  `is_completed` TINYINT(1) NOT NULL DEFAULT '0',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `group_id`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 퀘스트 수행 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_achievement_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_achievement_record` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '업적의 타입 식별 코드\n\n- GTC 값이다.',
  `character_id` BIGINT(20) UNSIGNED NOT NULL,
  `group_high` INT(11) NOT NULL DEFAULT '0' COMMENT '업적의 상위 그룹\n: eAchievementGroupHigh의 값과 같다.',
  `group_mid` INT(11) NOT NULL DEFAULT '0' COMMENT '업적의 중위 그룹\n: eAchievementGroupMid의 값과 같다.',
  `group_low` INT(11) NOT NULL DEFAULT '0' COMMENT '업적의 하위 그룹\n: eAchievementGroupLow의 값과 같다.',
  `grade` INT(11) NOT NULL DEFAULT '0' COMMENT '진행 중인 업적 단계\n\n-  같은 타입의 기록 목표를 여러 단계에 걸쳐 달성해야 한다.',
  `record` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '업적 종류의 현재 기록\n\n- 이 기록들은 group_high - group_mid - group_low 조합이 같은 업적들끼리 공유한다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`, `character_id`, `group_high`, `group_mid`, `group_low`))
ENGINE = InnoDB
COMMENT = '플레이어, 캐릭터 별 업적 관련 데이터와 진행 단계의 기록';


-- -----------------------------------------------------
-- Table `eod_game`.`table_shop_buy_count`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_shop_buy_count` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL,
  `character_id` BIGINT(20) UNSIGNED NOT NULL,
  `product_code` INT(11) NOT NULL DEFAULT '0',
  `count` TINYINT(4) NOT NULL DEFAULT '0',
  `purchased_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00',
  PRIMARY KEY (`user_id`, `character_id`, `product_code`))
ENGINE = InnoDB
COMMENT = '플레이어, 캐릭터 별 상품 구매 횟수 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_shop_servant_piece`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_shop_servant_piece` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL,
  `product_list` VARCHAR(100) NOT NULL DEFAULT '',
  `is_bought` INT(11) NOT NULL DEFAULT '0',
  `refreshed_count_by_gem` INT NOT NULL DEFAULT '0',
  `refreshed_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00',
  PRIMARY KEY (`user_id`))
ENGINE = InnoDB
COMMENT = '플레이어 별 조력자 조각 상점의 이용 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_tutorial`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_tutorial` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL,
  `tutorial_code` INT(11) NOT NULL,
  `completed_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00',
  PRIMARY KEY (`character_id`, `tutorial_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 튜토리얼 진행 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_story`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_story` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `story_code` INT(11) NOT NULL COMMENT '스토리의 타입 식별 코드',
  `completed_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '완료한 일시',
  PRIMARY KEY (`character_id`, `story_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 스토리 진행 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_post`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_post` (
  `no` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '우편의 순번',
  `receiver_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '수신자의 사용자 ID',
  `receiver_character_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '수신자의 캐릭터 ID',
  `sender_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '발신자의 사용자 ID',
  `text_key` INT(11) NOT NULL DEFAULT '0' COMMENT '사전 정의한 메시지 내용이 들어 있는 타입 식별 코드',
  `item_code` INT(11) NOT NULL DEFAULT '0' COMMENT '첨부물의 아이템 식별 코드',
  `amount` INT(11) NOT NULL DEFAULT '0' COMMENT '첨부물의 양',
  `state` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0 : 받기 가능한 우편\n1 : 유효기간 지나 삭제된 우편\n2 : 운영자가 삭제한 우편',
  `received_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '수신한 일시',
  PRIMARY KEY (`no`),
  INDEX `table_post_receiver_id_receiver_character_id` (`receiver_id` ASC, `receiver_character_id` ASC))
ENGINE = InnoDB
COMMENT = '우편 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_occupation_war_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_occupation_war_accomplishment` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어 ID',
  `mode` TINYINT(4) NOT NULL COMMENT '점령전 모드의 종류\n: eOccupationWarMode의 값과 같다.',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증 번호',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`, `mode`))
ENGINE = InnoDB
COMMENT = '플레이어 별 점령전 스테이지의 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_servant_collection_reward`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_servant_collection_reward` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `servant_grade` TINYINT(4) NOT NULL COMMENT '조력자의 등급',
  `is_rewarded` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '조력자 도감에 대한 보상을 받았는지 여부',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `servant_grade`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 조력자 수집과 그 보상에 대한 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_occupation_war_reward`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_occupation_war_reward` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어 ID',
  `season_number` INT(11) NOT NULL COMMENT '시즌 번호\n: 시즌 번호는 점령전 모드 별로 따로 매긴다.',
  `reward_code` INT(11) NOT NULL COMMENT '보상 정보의 타입 식별 코드\n: [OccupationReward.xml]의 <RewardGeneralCode> 필드의 값이다.',
  `state` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '업적의 수행 상태\n: eAchievementState의 값과 같다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`, `season_number`, `reward_code`))
ENGINE = InnoDB
COMMENT = '플레이어 별 점령전 보상 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_occupation_war_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_occupation_war_record` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어 ID',
  `mode` TINYINT(4) NOT NULL COMMENT '점령전 모드의 종류\n: eOccupationWarMode의 값과 같다.',
  `season_number` INT(11) NOT NULL COMMENT '시즌 번호\n: 시즌 번호는 점령전 모드 별로 따로 매긴다.',
  `record_type` TINYINT(4) NOT NULL COMMENT '무엇에 대한 기록을 나타내는지에 대한 타입\n: eOccupationWarRecordType과 같다.',
  `record` INT(11) NOT NULL DEFAULT '0' COMMENT '기록 값\n: 이 값이 어떤 성격의 기록인지는 record_type에 달려 있다.',
  `grade` INT(11) NOT NULL DEFAULT '0' COMMENT '진행 중인 단계\n\n-  같은 타입의 기록 목표를 여러 단계에 걸쳐 달성해야 한다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`, `mode`, `season_number`, `record_type`))
ENGINE = InnoDB
COMMENT = '플레이어 별 점령전 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_guardian_raid_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_guardian_raid_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `stage_grade` INT(11) NOT NULL COMMENT '대상 스테이지의 등급',
  `party_play_mode` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '파티 플레이 모드\n: ePartyPlayMode의 값과 같다.',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증 번호\n: 파티 플레이인 경우에만 검사한다.',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `revive_instantly_count` INT(11) NULL DEFAULT '0' COMMENT '이 초월 스테이지에서 즉시 부활한 횟수',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`stage_grade`, `character_id`))
ENGINE = InnoDB
COMMENT = '플레이어 별 수호자 레이드 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_pet`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_pet` (
  `pet_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '펫의 고유 ID',
  `owner_character_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '펫의 주인이 되는 캐릭터의 ID',
  `pet_code` INT(11) NOT NULL DEFAULT '0' COMMENT '펫의 타입 식별 코드',
  `grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '펫의 현재 등급',
  `basic_ability_code` INT(11) NOT NULL DEFAULT '0' COMMENT '기본 능력의 타입 식별 코드',
  `basic_ability_value` INT(11) NOT NULL DEFAULT '0' COMMENT '기본 능력의 값',
  `equipped_ability_code` INT(11) NOT NULL DEFAULT '0' COMMENT '장착한 능력의 타입 식별 코드',
  `equipped_ability_value` INT(11) NOT NULL DEFAULT '0' COMMENT '장착한 능력의 값',
  `equipped_skin_code` INT(11) NOT NULL DEFAULT '0' COMMENT '장착한 스킨의 타입 식별 코드',
  `equipped_chroma_code` INT(11) NOT NULL DEFAULT '0' COMMENT '적용한 색상의 타입 식별 코드',
  `update_datetime` DATETIME NOT NULL DEFAULT '1001-01-01 00:00:00' COMMENT '갱신일시',
  `creation_datetime` DATETIME NOT NULL DEFAULT '1001-01-01 00:00:00' COMMENT '생성일시',
  PRIMARY KEY (`pet_id`),
  INDEX `idx_table_pet_owner_character_id_pet_code` (`owner_character_id` ASC, `pet_code` ASC))
ENGINE = InnoDB
COMMENT = '펫 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_pet_decoration`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_pet_decoration` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `pet_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '펫 ID',
  `decoration_type` TINYINT(4) NOT NULL COMMENT '장식 타입',
  `decoration_code` INT(11) NOT NULL COMMENT '장식물의 타입 식별 코드',
  `creation_datetime` DATETIME NOT NULL DEFAULT '1001-01-01 00:00:00' COMMENT '생성일시',
  PRIMARY KEY (`character_id`, `pet_id`, `decoration_type`, `decoration_code`))
ENGINE = InnoDB
COMMENT = '펫 장식 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_attendance_special`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_attendance_special` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어 캐릭터의 ID',
  `event_code` INT(11) NOT NULL COMMENT '이벤트 종류의 타입 식별 코드',
  `attendance_count` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '출석 횟수',
  `check_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '출석을 점검한 일시',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `event_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 특별 출석과 보상에 대한 기록';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_arena_async_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_arena_async_record` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL,
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 인증번호\n\n- 결투장에 입장할 때마다 바뀐다.\n\n- 클라이언트는 결투장에 입장할 때, 매칭 서버에 이 인증번호를 제출해야만 한다.\n\n- 결투장 대전의 결과로 보상을 받을 때, 이 인증번호로 보상 수령 여부를 검증한다. (검증 주체는 매칭 서버)',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '결투장(비동기식)의 시작 일시',
  `remain_play_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 오늘 남은 플레이 횟수',
  `play_count_max` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식) 최대 플레이 횟수',
  `reset_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 플레이 횟수제한을 초기화한 횟수',
  `reset_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '결투장(비동기식)의 플레이 횟수를 초기화한 일시',
  `straight_win_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 현재 연속 승리 횟수\n: 한 번이라도 패하면 0으로 되돌아감.',
  `straight_defeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '결투장(비동기식)의 현재 연속 패배 횟수\n: 한 번이라도 승리하면 0으로 되돌아감.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신 일시',
  PRIMARY KEY (`user_id`))
ENGINE = InnoDB
COMMENT = '플레이어 별 결투장(비동기식) 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_west_act_record`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_west_act_record` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '액트 번호',
  `repeat_count` INT(11) NOT NULL DEFAULT '0' COMMENT '현재까지 누적된 반복횟수\n\n- 반복횟수는 보상을 받을 때마다, 보상을 지급하는 반복 횟수의 단위만큼 차감한다.\n: 이는 이 필드의 값이 0이 되거나, 혹은 더 이상 보상을 지급할 수 있는 반복 횟수 단위에 미치지 못하게 될 때까지 반복한다.',
  `is_rewarded_first_repetition` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '첫 번째 반복인지 여부\n\n- 반복 보상을 처음으로 받는 경우와, 그 이후에 받는 경우의 보상 지급 방식이 다르다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신 일시',
  PRIMARY KEY (`character_id`, `act_number`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 서부 지역 스테이지의 액트 기록 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_stage_west_accomplishment`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_stage_west_accomplishment` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `act_number` TINYINT(4) NOT NULL COMMENT '스테이지의 액트 번호',
  `stage_number_in_act` TINYINT(4) NOT NULL COMMENT '스테이지 액트에서의 스테이지 번호',
  `stage_auth_number` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '스테이지 인증번호',
  `start_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '스테이지를 시작한 일시\n\n- 스테이지 진행 시간을 판정하기 위해 사용한다.\n\n- 즉시완료권을 사용할 때는 기록하지 않는다.',
  `clear_grade` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '스테이지의 완료 등급\n\n- 0이면 아직 이 스테이지는 완료하지 않은 상태이다.\n\n- 최대 등급은 기획에 따라 그 값이 달라진다.\n',
  `top_score` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최대 점수',
  `top_second` INT(11) NOT NULL DEFAULT '0' COMMENT '이 스테이지에서 달성한 최고 시간\n\n- 대개, 완료한 가장 짧은 시간을 나타낸다.',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '캐릭터가 해당 스테이지를 플레이할 수 있는 횟수를 초기화한 일시',
  PRIMARY KEY (`character_id`, `act_number`, `stage_number_in_act`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 서부 지역 스테이지 성취 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_re_purchase_count`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_re_purchase_count` (
  `character_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '캐릭터의 ID',
  `product_code` INT(11) NOT NULL COMMENT '상품의 타입 식별 코드',
  `count` INT(11) NOT NULL DEFAULT '0' COMMENT '구매 횟수',
  `accumulate_count` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '누적 구매 횟수',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`character_id`, `product_code`))
ENGINE = InnoDB
COMMENT = '캐릭터 별 상품 재구매 횟수의 정보';


-- -----------------------------------------------------
-- Table `eod_game`.`table_monthly_product`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `eod_game`.`table_monthly_product` (
  `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '플레이어의 ID',
  `product_code` INT(11) NOT NULL COMMENT '상품의 타입 식별 코드',
  `remain_count` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '남은 횟수',
  `update_datetime` DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '갱신일시',
  PRIMARY KEY (`user_id`, `product_code`))
ENGINE = InnoDB
COMMENT = '플레이어 별 월간 단위 상품 구매 정보';


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
