Backend Ddevelopment
โ๐[Backend Development] increase๋ฉ์๋ ๋ด๋ถ for๋ฌธ ์คํ ๊ณผ์ ์์ธ ๋ถ์โ
package kobe.board.comment.entity;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Getter
@ToString
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CommentPath {
private String path;
private static final String CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final int DEPTH_CHUNK_SIZE = 5;
private static final int MAX_DEPTH = 5;
// MIN_CHUNK = "00000", MAX_CHUNK = "zzzzz"
private static final String MIN_CHUNK = String.valueOf(CHARSET.charAt(0)).repeat(DEPTH_CHUNK_SIZE);
private static final String MAX_CHUNK = String.valueOf(CHARSET.charAt(CHARSET.length() - 1)).repeat(DEPTH_CHUNK_SIZE);
public static CommentPath create(String path) {
if (isDepthOverflowed(path)) {
throw new IllegalStateException("depth overflowed");
}
CommentPath commentPath = new CommentPath();
commentPath.path = path;
return commentPath;
}
private static boolean isDepthOverflowed(String path) {
return calculateDepth(path) > MAX_DEPTH;
}
private static int calculateDepth(String path) {
// 25๊ฐ์ ๋ฌธ์์ด / 5 = 5depth
return path.length() / DEPTH_CHUNK_SIZE;
}
// CommentPath ํด๋์ค์ path์ depth๋ฅผ ๊ตฌํ๋ ๋งค์๋
public int getDepth() {
return calculateDepth(path);
}
// root์ธ์ง ํ์ธํ๋ ๋งค์๋
public boolean isRoot() {
// ํ์ฌ์ depth๊ฐ 1์ธ์ง ํ์ธํด์ฃผ๋ฉด ๋จ
return calculateDepth(path) == 1;
}
// ํ์ฌ path์ parentPath๋ฅผ ๋ฐํํด์ฃผ๋ ๋งค์๋
public String getParentPath() {
// ๋ 5์๋ฆฌ๋ง ์๋ผ๋ด๋ฉด ๋จ
return path.substring(0, path.length() - DEPTH_CHUNK_SIZE);
}
// ํ์ฌ path์ ํ์ ๋๊ธ์ path์ ๋ง๋๋ ๋งค์๋
public CommentPath createChildCommentPath(String descendantsTopPath) {
if (descendantsTopPath == null) {
return CommentPath.create(path + MIN_CHUNK);
}
String childrenTopPath = findChildrenTopPath(descendantsTopPath);
return CommentPath.create(increase(childrenTopPath));
}
// 00a0z0000200000 <- descendantsTopPath
private String findChildrenTopPath(String descendantsTopPath) {
return descendantsTopPath.substring(0, (getDepth() + 1) * DEPTH_CHUNK_SIZE);
}
private String increase(String path) {
// path์์ ๊ฐ์ฅ ๋ง์ง๋ง 5์๋ฆฌ๋ฅผ ์๋ฅธ ๊ฒ
String lastChunk = path.substring(path.length() - DEPTH_CHUNK_SIZE);
if (isChunkOverflowed(lastChunk)) {
throw new IllegalStateException("chunk overflowed");
}
// Character set์ ๊ธธ์ด
int charsetLength = CHARSET.length();
// lastChunk๋ฅผ 10์ง์๋ก ๋จผ์ ๋ณํํ๊ธฐ ์ํ ๊ฐ์ ์ ์ฅ
int value = 0;
for (char character : lastChunk.toCharArray()) {
value = value * charsetLength + CHARSET.indexOf(character);
System.out.println("value ====> " + value);
System.out.println("CHARSET.indexOf ====> " + CHARSET.indexOf(character));
}
value = value + 1;
String result = "";
for (int i = 0; i < DEPTH_CHUNK_SIZE; i++) {
result = CHARSET.charAt(value % charsetLength) + result;
value /= charsetLength;
}
return path.substring(0, path.length() - DEPTH_CHUNK_SIZE) + result;
}
private boolean isChunkOverflowed(String lastChunk) {
return MAX_CHUNK.equals(lastChunk);
}
}
๐ for ๋ฌธ ์คํ ๊ณผ์ ์์ธ ๋ถ์
- ํด๋น for ansdms ์ฃผ์ด์ง value(10์ง์)๋ฅผ CHARSET(62์ง์)๋ก ๋ณํํ์ฌ ๋ฌธ์์ด(result)์ ์์ฑํ๋ ๊ณผ์ ์
๋๋ค.
1๏ธโฃ for ๋ฌธ ์ฝ๋
for (int i = 0; i < DEPTH_CHUNK_SIZE; i++) {
result = CHARSET.charAt(value % charsetLength) + result;
value /= charsetLength;
}
โ
์ฃผ์ ๊ฐ๋
- value % charsetLength โ 62์ง์์์ ๊ฐ์ฅ ๋ฎ์ ์๋ฆฌ์(์ค๋ฅธ์ชฝ ๋)๋ฅผ ๊ตฌํจ
- CHARSET.charAt(value % charsetLenht) โ CHARSET์์ ํด๋น ์ธ๋ฑ์ค์ ๋ฌธ์(0~9, A~Z, a~z)๋ฅผ ๊ฐ์ ธ์ด
- value /= charsetLength โ ๋ค์ ์๋ฆฌ์๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด value๋ฅผ 62๋ก ๋๋
- result = CHARSET.charAt(value % charsetLenght) + resultl โ ๋ฌธ์์ด์ ์์ ์ถ๊ฐํ์ฌ ๋ณํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ ๋ค
2๏ธโฃ for ๋ฌธ ์คํ ๊ณผ์ ๋จ๊ณ๋ณ ๋ถ์
๐ ์์ 1: value = 1, charsetLenght = 62, DEPTH_CHUNK_SIZE = 5
โ
์ด๊ธฐ ๊ฐ
โ
๋ฐ๋ณต ๊ณผ์
๋ฐ๋ณต |
value |
value % 62 |
CHARSET.charAt(value % 62) |
result |
value /= 62 |
i=0 |
1 |
1 |
โ1โ |
โ1โ |
0 |
i=1 |
0 |
0 |
โ0โ |
โ01โ |
0 |
i=2 |
0 |
0 |
โ0โ |
โ001โ |
0 |
i=3 |
0 |
0 |
โ0โ |
โ0001โ |
0 |
i=4 |
0 |
0 |
โ0โ |
โ00001โ |
0 |
โ
์ต์ข
๊ฒฐ๊ณผ
๐ ์์ 2: value = 62
โ
์ด๊ธฐ ๊ฐ
โ
๋ฐ๋ณต ๊ณผ์
๋ฐ๋ณต |
value |
value % 62 |
CHARSET.charAt(value % 62) |
result |
value /= 62 |
i=0 |
62 |
0 |
โ0โ |
โ0โ |
1 |
i=1 |
1 |
1 |
โ1โ |
โ10โ |
0 |
i=2 |
0 |
0 |
โ0โ |
โ010โ |
0 |
i=3 |
0 |
0 |
โ0โ |
โ0010โ |
0 |
i=4 |
0 |
0 |
โ0โ |
โ00010โ |
0 |
โ
์ต์ข
๊ฒฐ๊ณผ
๐ ์์ 3: value = 3843
โ
์ด๊ธฐ ๊ฐ
value = 3843;
resutl = "";
โ
๋ฐ๋ณต ๊ณผ์
๋ฐ๋ณต |
value |
value % 62 |
CHARSET.charAt(value % 62) |
result |
value /= 62 |
i=0 |
3843 |
61 |
โzโ |
โzโ |
61 |
i=1 |
61 |
61 |
โzโ |
โzzโ |
0 |
i=2 |
0 |
0 |
โ0โ |
โ0zzโ |
0 |
i=3 |
0 |
0 |
โ0โ |
โ00zzโ |
0 |
i=4 |
0 |
0 |
โ0โ |
โ000zzโ |
0 |
โ
์ต์ข
๊ฒฐ๊ณผ
๐ ํต์ฌ ์ ๋ฆฌ
๐ for ๋ฌธ์ด ํ๋ ์ผ
-
- value(10์ง์)๋ฅผ 62์ง์ ๋ฌธ์์ด๋ก ๋ณํํ๋ค.
-
- CHARSET.charAt(value % 62)๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฅ ๋ฎ์ ์๋ฆฌ์๋ถํฐ ๋ณํํ๋ค.
- 3.๋ณํ๋ ๋ฌธ์๋ฅผ result ์์ ์ถ๊ฐ(+ result)
-
- value /= 62 ํ์ฌ ๋ค์ ์๋ฆฌ์๋ฅผ ๊ณ์ฐ.
-
- ์ต์ข
์ ์ผ๋ก DEPTH_CHUNK_SIZE(5)๋งํผ ๋ฐ๋ณตํ์ฌ 5์๋ฆฌ ๋ฌธ์์ด์ ๋ง๋ ๋ค.
๐ ๊ฒฐ๋ก
- value์ ์์ ์๋ฆฌ์๋ถํฐ ๋ณํํ์ฌ ๋ฌธ์์ด์ ๊ตฌ์ฑํ๋ค.
- 62์ง๋ฒ ๋ณํ์๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋๊ธ์ path๋ฅผ ์ฆ๊ฐ์ํค๋ ๋ฐ ํ์ฉํ๋ค.