-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' of https://github.com/boostcampwm-2024/web33-Nocta …
…into Feature/#119_모달_공통_컴포넌트_구현
- Loading branch information
Showing
14 changed files
with
303 additions
and
367 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,136 +1,111 @@ | ||
import { LinkedList } from "./LinkedList"; | ||
import { NodeId, Node } from "./Node"; | ||
import { | ||
RemoteInsertOperation, | ||
RemoteDeleteOperation, | ||
SerializedProps, | ||
Block, | ||
Char, | ||
CRDT as CRDTClassProps, | ||
} from "./Interfaces"; | ||
|
||
export class CRDT implements CRDTClassProps { | ||
import { CharId, BlockId, NodeId } from "./NodeId"; | ||
import { Node, Char, Block } from "./Node"; | ||
import { RemoteDeleteOperation, RemoteInsertOperation, SerializedProps } from "./Interfaces"; | ||
|
||
export class CRDT<T extends Node<NodeId>> { | ||
clock: number; | ||
client: number; | ||
LinkedList: LinkedList; | ||
LinkedList: LinkedList<T>; | ||
|
||
constructor(client: number) { | ||
this.clock = 0; // 이 CRDT의 논리적 시간 설정 | ||
this.clock = 0; | ||
this.client = client; | ||
this.LinkedList = new LinkedList(); | ||
this.LinkedList = new LinkedList<T>(); | ||
} | ||
|
||
/** | ||
* 로컬에서 삽입 연산을 수행하고, 원격에 전파할 연산 객체를 반환합니다. | ||
* @param index 삽입할 인덱스 | ||
* @param value 삽입할 값 | ||
* @returns 원격에 전파할 삽입 연산 객체 | ||
*/ | ||
localInsert(index: number, value: string): RemoteInsertOperation { | ||
const id = new NodeId((this.clock += 1), this.client); | ||
const id = | ||
this instanceof BlockCRDT | ||
? new CharId(this.clock + 1, this.client) | ||
: new BlockId(this.clock + 1, this.client); | ||
|
||
const remoteInsertion = this.LinkedList.insertAtIndex(index, value, id); | ||
this.clock += 1; | ||
return { node: remoteInsertion.node }; | ||
} | ||
|
||
/** | ||
* 로컬에서 삭제 연산을 수행하고, 원격에 전파할 연산 객체를 반환합니다. | ||
* @param index 삭제할 인덱스 | ||
* @returns 원격에 전파할 삭제 연산 객체 | ||
*/ | ||
localDelete(index: number): RemoteDeleteOperation { | ||
// 유효한 인덱스인지 확인 | ||
if (index < 0 || index >= this.LinkedList.spread().length) { | ||
throw new Error(`유효하지 않은 인덱스입니다: ${index}`); | ||
throw new Error(`Invalid index: ${index}`); | ||
} | ||
|
||
// 삭제할 노드 찾기 | ||
const nodeToDelete = this.LinkedList.findByIndex(index); | ||
if (!nodeToDelete) { | ||
throw new Error(`삭제할 노드를 찾을 수 없습니다. 인덱스: ${index}`); | ||
throw new Error(`Node not found at index: ${index}`); | ||
} | ||
|
||
// 삭제 연산 객체 생성 | ||
const operation: RemoteDeleteOperation = { | ||
targetId: nodeToDelete.id, | ||
clock: this.clock + 1, | ||
}; | ||
|
||
// 로컬 삭제 수행 | ||
this.LinkedList.deleteNode(nodeToDelete.id); | ||
|
||
// 클록 업데이트 | ||
this.clock += 1; | ||
|
||
return operation; | ||
} | ||
|
||
/** | ||
* 원격에서 삽입 연산을 수신했을 때 처리합니다. | ||
* @param operation 원격 삽입 연산 객체 | ||
*/ | ||
remoteInsert(operation: RemoteInsertOperation): void { | ||
const newNodeId = new NodeId(operation.node.id.clock, operation.node.id.client); | ||
const newNode = new Node(operation.node.value, newNodeId); | ||
const NodeIdClass = this instanceof BlockCRDT ? CharId : BlockId; | ||
const NodeClass = this instanceof BlockCRDT ? Char : Block; | ||
|
||
const newNodeId = new NodeIdClass(operation.node.id.clock, operation.node.id.client); | ||
const newNode = new NodeClass(operation.node.value, newNodeId) as T; | ||
newNode.next = operation.node.next; | ||
newNode.prev = operation.node.prev; | ||
|
||
this.LinkedList.insertById(newNode); | ||
// 동기화 논리적 시간 | ||
|
||
if (this.clock <= newNode.id.clock) { | ||
this.clock = newNode.id.clock + 1; | ||
} | ||
} | ||
|
||
/** | ||
* 원격에서 삭제 연산을 수신했을때 처리합니다. | ||
* @param operation 원격 삭제 연산 객체 | ||
*/ | ||
remoteDelete(operation: RemoteDeleteOperation): void { | ||
const { targetId, clock } = operation; | ||
if (targetId) { | ||
this.LinkedList.deleteNode(targetId); | ||
} | ||
// 동기화 논리적 시간 | ||
if (this.clock <= clock) { | ||
this.clock = clock + 1; | ||
} | ||
} | ||
|
||
/** | ||
* 현재 텍스트를 문자열로 반환합니다. | ||
* @returns 현재 텍스트 | ||
*/ | ||
read(): string { | ||
return this.LinkedList.stringify(); | ||
} | ||
|
||
/** | ||
* 현재 텍스트를 배열로 반환합니다. | ||
* @returns 현재 텍스트 배열 | ||
*/ | ||
spread(): Block[] | Char[] { | ||
spread(): T[] { | ||
return this.LinkedList.spread(); | ||
} | ||
|
||
/** | ||
* textLinkedList를 반환하는 getter 메서드 | ||
* @returns LinkedList 인스턴스 | ||
*/ | ||
public getTextLinkedList(): LinkedList { | ||
return this.LinkedList; | ||
} | ||
|
||
/** | ||
* CRDT의 상태를 직렬화 가능한 객체로 반환합니다. | ||
* @returns 직렬화 가능한 CRDT 상태 | ||
*/ | ||
serialize(): SerializedProps { | ||
serialize(): SerializedProps<T> { | ||
return { | ||
clock: this.clock, | ||
client: this.client, | ||
textLinkedList: { | ||
LinkedList: { | ||
head: this.LinkedList.head, | ||
nodeMap: this.LinkedList.nodeMap, | ||
}, | ||
}; | ||
} | ||
} | ||
|
||
export class EditorCRDT extends CRDT<Block> { | ||
currentBlock: Block | null; | ||
|
||
constructor(client: number) { | ||
super(client); | ||
this.currentBlock = null; | ||
} | ||
} | ||
|
||
export class BlockCRDT extends CRDT<Char> { | ||
currentCaret: number; | ||
|
||
constructor(client: number) { | ||
super(client); | ||
this.currentCaret = 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.