Last active
September 9, 2021 10:06
-
-
Save Rishabh-malhotraa/b351aa74178274fa0321fa8821a2c2dc to your computer and use it in GitHub Desktop.
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
interface OperationType { | |
op: string; | |
count?: number; | |
chars?: string; | |
} | |
class OperationTransformation { | |
private cursorPosition = 0; | |
/*update the cursor position*/ | |
public skip(text: string, count: number) { | |
this.cursorPosition = Math.min(count + this.cursorPosition, text.length); // truncates count + cusor_position if it goes beyond text.size() | |
} | |
public insert(text: string, insertText: string) { | |
text = | |
text.substr(0, this.cursorPosition) + | |
insertText + | |
text.substr(this.cursorPosition); | |
this.skip(text, insertText.length); | |
return text; | |
} | |
public delete(text: string, count: number) { | |
return ( | |
text.substr(0, this.cursorPosition) + | |
text.substr(this.cursorPosition + count) // substr return "" if start position > length of string | |
); | |
} | |
public getCursorPosition() { | |
return this.cursorPosition; | |
} | |
} | |
function isValid(stale: string, latest: string, otjson: string): boolean { | |
const ot = new OperationTransformation(); | |
const operations: OperationType[] = JSON.parse(otjson); | |
for (const { op, chars, count } of operations) { | |
if (op === 'skip') { | |
if (ot.getCursorPosition() + count >= stale.length) return false; // if we skip past end | |
ot.skip(stale, count); | |
} else if (op === 'insert') { | |
stale = ot.insert(stale, chars); | |
} else if (op === 'delete') { | |
if (ot.getCursorPosition() + count >= stale.length) return false; // if we delete past end | |
stale = ot.delete(stale, count); | |
} | |
} | |
console.log(stale === latest ? 'true' : 'false'); | |
return stale === latest; | |
} | |
/* | |
=================================================================================================== | |
*/ | |
isValid( | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'This Editor uses operational transformations.', | |
'[{"op": "skip", "count": 40}, {"op": "delete", "count": 47}]' | |
); // true | |
isValid( | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'This Editor uses operational transformations.', | |
'[{"op": "skip", "count": 45}, {"op": "delete", "count": 47}]' | |
); // false, delete past end | |
isValid( | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'This Editor uses operational transformations.', | |
'[{"op": "skip", "count": 40}, {"op": "delete", "count": 47}, {"op": "skip", "count": 2}]' | |
); // false, skip past end | |
isValid( | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'We use operational transformations to keep everyone in a multiplayer repl in sync.', | |
'[{"op": "delete", "count": 7}, {"op": "insert", "chars": "We"}, {"op": "skip", "count": 4}, {"op": "delete", "count": 1}]' | |
); // true | |
isValid( | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'This Editor uses operational transformations to keep everyone in a multiplayer repl in sync.', | |
'[]' | |
); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment