쁘띠 TFT 프로젝트
유효성 평가 미들웨어 조정
- 기존에 agent를 찾는 변수로 agent_name(str)과 agent_key(int)를 사용했는데, 이를 통합하여 key만 사용하게 설계함
-
기존 팀편성 / 대표 챔피언 설정 api 수정
- 찾는 변수를 name에서 key로 변경 및 에러 메시지를 수정하였다.
// 팀편성 API 내부 myAgent[i] = await prisma.myAgents.findFirst({ where: { agentKey: +formation[i], userKey: +key } }) //보유 챔피언 확인 if (!myAgent[i]) return res .status(400) .json({errorMessage: `${agent[i].name}/${formation[i]}(은)는 현재 보유한 챔피언이 아닙니다.`}) if (agent[i].position === "tanker") { tank = true; } // 챔피언 설정 API 내부 const myAgent = await prisma.myAgents.findFirst({ where: { agentKey: +agent.agentKey, userKey: +key } }) // 보유 챔피언 확인 if (!myAgent) return res .status(400) .json({ errorMessage: `${agent.name}/${agent.agentKey}(은)는 현재 보유한 챔피언이 아닙니다.`})
-
유효성 평가 미들웨어 수정
-
기존에 미들웨어 함수를 2개로 구분지어 export 하였으나, 이를 하나로 합칠 예정이기에 export default로 수정 해주었다.
-
추가로 배열(다중입력)의 경우도 각각 유효성 평가를 할 수 있도록 재설계 해주었다.
// 배열 값인지 판정 if (Array.isArray(agentValues?.formation) || Array.isArray(agentValues) ) { const agents = []; // 팀편성의 경우 if (agentValues?.formation) { for (let agentKey of agentValues.formation) { // 입력값 유효성 평가 if (!Number.isInteger(agentKey)) return res .status(400) .json({ errorMessage: "선택할 챔피언의 <agent_key>를 숫자로 입력해주세요" }) // 챔피언 존재 여부 확인 const agent = await prisma.agents.findFirst({ where: { agentKey } }) if (!agent) return res .status(404) .json({ errorMessage: `<agent_key> ${agentKey}에 해당하는 챔피언은 존재하지 않습니다` }) // 챔피언 정보 할당 agents.push(agent) } // 일반 배열 } else { for (let { agent } of agentValues) { // 입력값 유효성 평가 if (!Number.isInteger(+agent)) return res .status(400) .json({ errorMessage: "선택할 챔피언의 <agent_key>를 숫자로 입력해주세요" }) // 챔피언 존재 여부 확인 const agentVerify = await prisma.agents.findFirst({ where: { agentKey: +agent } }) if (!agentVerify) return res .status(404) .json({ errorMessage: `<agent_key> ${agentKey}에 해당하는 챔피언은 존재하지 않습니다` }) // 챔피언 정보 할당 agents.push(agentVerify) } } } // 챔피언 정보 반환 req.agent = agents
-
챔피언 매각 API 구현
- 챔피언 매각을 다중으로도 가능하게 설계를 하기로 했다!
// 출력용 값 저장
let resJson = [];
// 다중 입력 확인
if (Array.isArray(agent)) {
for (let i = 0;i < agent.length;i++) {
const count = req.body[i].count
const myAgent = await prisma.myAgents.findFirst({ where: { userKey: +key, agentKey: agent[i].agentKey } })
const amount = agent[i].grade === "s" ? 300000 * +count : 100000 * +count
console.log(agent)
if (!myAgent || myAgent.count < count) {0
resJson = [...resJson, { errorMessage: `판매할 챔피언(${agent[i].name})(이)가 부족합니다` }]
} else {
// 저번 피드백으로 업데이트,생성 에 관계성이 있을 경우 한번의 쿼리로 해결하게 설계했다.
const update = await prisma.users.update({
where: { userKey: +key },
data: {
// 유저의 지갑 cash 업데이트
asset: {
update: {
data: {
cash: { increment: +amount }
}
}
},
// 유저가 소유한 챔피언(인벤토리 개념) count 업데이트
myAgent: {
update: {
where: { myAgentKey: +myAgent.myAgentKey },
data: {
count: { decrement: +count }
}
}
}
}
})
resJson = [...resJson, {
message: `성공적으로 챔피언 ${agent[i].name}(을)를 ${count}만큼 판매하였습니다.`,
amount: `+${amount}`
}]
}
}
}
- 추가로 count가 0이하인 myAgent들을 삭제하는 로직을 추가했다
// 남은 숫자가 0 이하인 챔피언 삭제
const deleteMyAgent = await prisma.myAgents.deleteMany({where: {count: {lte: 0}, userKey: +key}})
프로젝트 병합 및 기능별 묶기
- 각자 작업을 마친 파일들을 한 branch에(dev) 병합한 후 기능에 따라 묶어주는 작업을 하였다!
- 이후 미들웨어들을 사용하는 API들에 중복된 로직을 간략화(리팩토링)해주며 미들웨어를 적용 시켜주었다.
개선점 분석
- 발표 자료도 준비하기 시작해야겠다
지식창고
알고리즘 코드 카타
대충 만든 자판
- 문제
휴대폰의 자판은 컴퓨터 키보드 자판과는 다르게 하나의 키에 여러 개의 문자가 할당될 수 있습니다. 키 하나에 여러 문자가 할당된 경우, 동일한 키를 연속해서 빠르게 누르면 할당된 순서대로 문자가 바뀝니다.
같은 규칙을 적용해 아무렇게나 만든 휴대폰 자판이 있습니다. 이 휴대폰 자판은 키의 개수가 1개부터 최대 100개까지 있을 수 있으며, 특정 키를 눌렀을 때 입력되는 문자들도 무작위로 배열되어 있습니다. 또, 같은 문자가 자판 전체에 여러 번 할당된 경우도 있고, 키 하나에 같은 문자가 여러 번 할당된 경우도 있습니다. 심지어 아예 할당되지 않은 경우도 있습니다. 따라서 몇몇 문자열은 작성할 수 없을 수도 있습니다.
이 휴대폰 자판을 이용해 특정 문자열을 작성할 때, 키를 최소 몇 번 눌러야 그 문자열을 작성할 수 있는지 알아보고자 합니다.
1번 키부터 차례대로 할당된 문자들이 순서대로 담긴 문자열배열 keymap과 입력하려는 문자열들이 담긴 문자열 배열 targets가 주어질 때, 각 문자열을 작성하기 위해 키를 최소 몇 번씩 눌러야 하는지 순서대로 배열에 담아 return 하는 solution 함수를 완성해 주세요.
-
조건
-
1 ≤ keymap의 길이 ≤ 100
-
1 ≤ keymap의 원소의 길이 ≤ 100
-
keymap[i]는 i + 1번 키를 눌렀을 때 순서대로 바뀌는 문자를 의미합니다.
예를 들어 keymap[0] = “ABACD” 인 경우 1번 키를 한 번 누르면 A,
두 번 누르면 B, 세 번 누르면 A 가 됩니다. -
keymap의 원소의 길이는 서로 다를 수 있습니다.
-
keymap의 원소는 알파벳 대문자로만 이루어져 있습니다.
-
1 ≤ targets의 길이 ≤ 100
-
1 ≤ targets의 원소의 길이 ≤ 100
-
targets의 원소는 알파벳 대문자로만 이루어져 있습니다.
-
function solution(keymap, targets) {
var answer = [];
for (let str of targets) {
let total_count = 0;
// 문자당 누름 횟수 찾기
for (let i = 0;i < str.length;i++) {
let count = 0;
const x = str[i]
// 문자 최소로 찾기
for (let j = 0;j < keymap.length;j++) {
if (!keymap[j].includes(x)) continue
if (count <= 0) count = keymap[j].indexOf(x)+1
else count = Math.min(count,keymap[j].indexOf(x)+1)
}
// 없을 경우 나가기
if (count === 0) {
answer.push(-1)
total_count = ""
break
}
// 한 글자에 필요한 누름 횟수를 총 누름 횟수에 더하기
total_count += count
}
if (total_count > 0 ) {
answer.push(total_count)
}
}
return answer;
}
- 다른 코드 분석
function solution(keymap, targets) {
const answer = [];
const map = {}
for (const items of keymap) {
/*문자 당 최소 누름 횟수를 map객체에 A(문자) : 1(횟수) 형태로 저장
[index+1]은 누름 횟수를 뜻함 (A 가 keymap의 0번 일 때 1번 누른 횟수이기에) */
items.split('').map((item, index) => map[item] = (map[item] < index+1 ? map[item] : index+1))
}
// 누름 횟수 확인
for (const items of targets) {
/* reduce 를 이용해 map{}에서 글자를 찾아 최소 누름 횟수를 더한 후 넣음,
또한 못찾을 경우 대신 -1을 넣음 (cur에 undefine이 들어가 최종값이 NaN이 됨)*/
answer.push(items.split('').reduce((cur, item) => cur += map[item], 0) || -1)
}
return answer;
}