카테고리 없음

[멀티,모바일(안드로이드),전략] 오목 APP Script

김조성준 2024. 10. 19. 16:22

1. App Script


 

구글 스프레드 시트의 ID를 이용하여 해당 Sheet의 정보에 접근하고 이용/갱신/추가하는 기능을 담당한다.

Post와 Get을 주로 지원한다. 갱신,추가하는 기능을 사용해야 하므로 Post 기능을 위주로 구현했다.

var sheetId = SpreadsheetApp.openById("Secret");
var sheet = sheetId.getSheets()[0]; // 첫번째 sheet 정보를 불러온다.
var cache = CacheService.getUserCache(); // 로그인 정보를 기록 (캐쉬해둔 정보는 6~12시간 뒤 소멸)
var p; // wwwform의 정보를 기록
var result, playerName, scoreValue; // 결과의 종류와 스코어를 저장한 변수

// 저장된 ID의 캐쉬를 삭제
function removeCache() { 
  if(cache.get("row_" + p.id) == null) 
    return;
  sheet.getRange(cache.get("row_" + p.id), 4).setValue(0);
  cache.removeAll(["id_" + p.id, "row_" + p.id]);
}

// POST로 호출된 값 반환
function response() {
  var json = {};
  json.result = result;
  json.playerName = playerName;
  json.scoreValue = scoreValue;
  jsonData = JSON.stringify(json);
  return ContentService.createTextOutput(jsonData);
}

// 특수 문자를 포함하고 있는지 확인 (부정한 공격을 방지하기 위함)
function specialCheck(val) {
  var specialExp = /[\{\}\[\]\/?.,;"|\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;

  if(specialExp.test(val)) 
    return false;
  else 
    return true;
}

// 정보를 받기만 한다. (스코어를 전달하는 기능만 구현)
function doGet(e) {
    p = e.parameter;
  
  // 특수 문자 포함을 방지
  if(!specialCheck(p.order) || !specialCheck(p.id)  || !specialCheck(p.password)  || !specialCheck(p.scoreValue))
    return ContentService.createTextOutput("");

  // 만약 p값이 없다면 null(빈 값)을 전달한다.
  if(!p.scoreValue)
    return ContentService.createTextOutput("");

  return ContentService.createTextOutput(p.scoreValue);
}

// 정보를 받고 갱신까지 할 수 있다.
function doPost(e) {
  p = e.parameter;

  // 특수 문자 포함을 방지
  if(!specialCheck(p.order) || !specialCheck(p.id)  || !specialCheck(p.password)  || !specialCheck(p.scoreValue))
    return ContentService.createTextOutput("");
  
  // 등록, 로그인, 로그아웃, 값 설정
  switch(p.order) {
    case "RENEW" : reNew(); break;
    case "OVERLAP" : overlap(); break;
    case "REGISTER": register(); break;
    case "LOGIN": login(); break;
    case "LOGOUT": removeCache(); logout(); break;
    case "SETSCOREVALUE": setScoreValue(); break;
    case "GETSCOREVALUE" : getScoreValue(); break;
  }

  return response();
}

// POST 결과를 갱신
function setResult(_result, _playerName, _scoreValue) {
  result = _result;
  playerName = _playerName;
  scoreValue = _scoreValue;
}

// 캐쉬를 갱신
function reNew() {
  if(cache.get("row_" + p.id) == null) {
    if(p.id.toString() != "") {
      var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1 , 4).getValues();
      for(i = 0; i < cell.length; i++) {
        if(cell[i][0] != p.id) 
          continue;
        sheet.getRange(i + 2, 4).setValue(0);
        setResult("ERROR", "", "-1000");
        return;
      }
    }
    setResult("ERROR", "", "-1000");
    return;
  }

  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1 , 4).getValues();
  var rowIndex = parseInt(cache.get("row_" + p.id)) - 2; 

  var cacheID = cell[rowIndex][0];
  var cachePassword = cell[rowIndex][1];

  for(i = 0; i < cell.length; i++) {
    if(cell[i][0] != cacheID || cell[i][1] != cachePassword) 
      continue;
    cache.put("id_" + p.id, cell[i][0]);
    cache.put("row_" + p.id, (i + 2).toString());
    setResult("RENEW", cell[i][0].toString(), cell[i][2].toString());
    sheet.getRange(i + 2, 4).setValue(1);
    return;
  }
  setResult("ERROR", "", "-1000");
}

// 중복된 ID인지를 확인
function overlap() {
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  // 해당 ID가 있다면 오류
  if(cell.some(row => row == p.id)) {
    setResult("ERROR", "", "-1000");
    return;
  }
  setResult("CANUSE", "", "1000");
}

// 계정 생성
function register() {       
  sheet.appendRow([p.id, p.password, p.scoreValue, 0]);
  setResult("RSUCCESS", p.id, "1000");
}

// 계정 로그인을 위해 ID와 PASSWORD를 조회
function getProfile() {
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1 , 2).getValues();

  for(i = 0; i < cell.length; i++) {
    if(cell[i][0] != p.id || cell[i][1] != p.password) 
      continue;

    cache.put("id_" + p.id, cell[i][0]);
    cache.put("row_" + p.id, (i + 2).toString());
    return true;
  }
  return false;
}

// 로그인 
function login() {
  if(cache.get("row_" + p.id) != null) 
    cache.removeAll(["id_" + p.id, "row_" + p.id]);

  if (!getProfile()) {
    setResult("ERROR", "", "-1000");
    return;
  }

  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1 , 4).getValues();
  var rowIndex = parseInt(cache.get("row_" + p.id)) - 2; // 배열 인덱스 보정

  if(cell[rowIndex][3].toString() == "1") {
    cache.removeAll(["id_" + p.id, "row_" + p.id]);
    setResult("OVERLAP", "", "-1000");
    return;
  }  
  // 스코어 값이 유효한지 확인
  var scoreValue = cell[rowIndex][2] !== undefined ? cell[rowIndex][2].toString() : "-1000"; // 기본값을 설정  
  setResult("LSUCCESS", cell[rowIndex][0].toString(), scoreValue);
  if(scoreValue.toString() != "-1000") {
    sheet.getRange(cache.get("row_" + p.id), 4).setValue(1);
  }
}

function logout() {
  setResult("LOGOUT", "", "");
}

// 스코어 점수 갱신
function setScoreValue() {
  if(cache.get("row_" + p.id) == null) {
    setResult("ERROR", "", "-1000");
    return;
  }

  sheet.getRange(cache.get("row_" + p.id), 3).setValue(p.scoreValue);
  setResult("SET", p.id.toString(), p.scoreValue.toString());
}

// 스코어 점수 받아오기
function getScoreValue() {
  if(cache.get("row_" + p.id) == null) {
    setResult("ERROR", "", "-1000");
    return;
  }
 
  var loadScore = sheet.getRange(cache.get("row_" + p.id), 3).getValue();
  setResult("GET", cache.get("id_" + p.id), loadScore);
}