우편함을 구현하는 방법

asked 2017-02-24 14:34:41 +0900

Seunghyun gravatar image

updated 2017-02-24 14:38:12 +0900

우편함 구현 예제

오브젝트 모델

{
  "User": {
    "Id": "String(16) KEY",
    "MyCharacter": "Character",
    "Mailbox": "Mail[] foreign"  // 우편함
  },
  "Character": {
    "Name": "String(24) KEY",
    "Exp": "Integer",
    "Level": "Integer",
    "Hp": "Integer",
    "Mp": "Integer"
  },
  "Mail": {
    "Title": "String(24)",
    "Content": "String(128)",
    "From": "String(16)",
    "Date": "Integer"
  }
}

(* 게임 특성 또는 구현에 따라 Mailbox 가 User 에 속하는 것이 아닌 독립된 Object 가 되는 것이 더 나을 수 있습니다.)

메일 보내기

  string to = ...;
  string from = ...;
  string title = ...;
  string content = ...;

  // 메일함 최대 크기
  const size_t kMaxSize = 30;

  // 메일을 수신할 유저의 메일함 가져오기
  Ptr< User> user_to = User::FetchById(to);
  if (not user_to) {
    // 에러 처리
    return;
  }
  ArrayRef< Object::Id> mailbox = user_to->GetMailbox();

  // 메일함 크기가 지정된 크기보다 작다면 늘려주기
  while (mailbox.Size() < kMaxSize) {
    mailbox.PushBack(Object::kNullId);
  }

  // 메일함에서 빈 공간 찾기
  int64_t index = mailbox.FindFirstEmptySlot();
  if (index == -1) {
    // 메일함 공간 부족
    return;
  }

  // 메일 생성하기
  Ptr< Mail> mail = Mail::Create();
  mail->SetTitle(title);
  mail->SetContent(content);
  mail->SetFrom(from);
  mail->SetDate(WallClock::GetTimestampInSec());

  // 메일함에 넣기
  mailbox.SetAt(index, mail->Id());

메일 보기

  string id = ...;

  // 메일함 가져오기
  Ptr< User> user = User::FetchById(id, kReadLock);
  if (not user) {
    // 에러 처리
    return;
  }
  ArrayRef< Ptr< Mail>> mailbox = user->FetchMailbox(kReadLock);

  // 메일 순서는 index 가 아니라 클라이언트에서 date 로 정렬해서 출력
  for (size_t i = 0; i < mailbox.Size(); ++i) {
    Ptr< Mail> mail = mailbox.GetAt(i);
    if (not mail) {
      continue;
    }

    // 클라이언트로 보내기. 이 예제에서는 로그로 출력.
    LOG(INFO) << "Title: " << mail->GetTitle();
    LOG(INFO) << "Content: " << mail->GetContent();
    LOG(INFO) << "From: " << mail->GetFrom();
    LOG(INFO) << "Date: " << WallClock::FromTimestampInSec(mail->GetDate());
    LOG(INFO) << "Index: " << i;
  }

메일 삭제하기

  string id = ...;
  int64_t index = ...;

  // 삭제할 메일의 object id 얻어오기
  Ptr< User> user = User::FetchById(id);
  if (not user) {
    // 에러 처리
    return;
  }
  ArrayRef< Object::Id> mailbox = user->GetMailbox();
  if (mailbox.Has(index)) {
    // 에러 처리
    return;
  }
  Object::Id mail_object_id = mailbox.GetAt(index);

  // 메일함에서 제거(빈 공간으로 표시하는 것)
  // EraseAt() 은 사용하지 않음
  mailbox.SetAt(index, Object::kNullId);

  // 메일 object 삭제하기.
  auto erase_mail_object = [mail_object_id]() {
    Ptr< Mail> mail = Mail::Fetch(mail_object_id);
    if (mail) {
      mail->Delete();
    }
  };

  Event::Invoke(erase_mail_object);

끝.

edit retag flag offensive close merge delete