Skip to content

Commit 2fb0a7f

Browse files
committed
Implemented handling conflict handling while undo
1 parent 8ff6fec commit 2fb0a7f

File tree

2 files changed

+100
-31
lines changed

2 files changed

+100
-31
lines changed

GoInfoGame/GoInfoGame/data/DatasyncManager.swift

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class DatasyncManager {
111111
print("📤 Syncing node ID: \(node.id)")
112112
let payload = node.asOSMNode()
113113
do {
114-
let status = try await syncNode(node: payload, exclude_gig_tags: exclude_gig_tags)
114+
let status = try await syncNode(node: payload, exclude_gig_tags: exclude_gig_tags, editedTags: node.tags.toDictionary())
115115
if status.result {
116116
DispatchQueue.main.async {
117117
self.dbInstance.assignChangesetId(obj: key, changesetId: 0, updatedVersion: status.version)
@@ -132,7 +132,7 @@ class DatasyncManager {
132132
print("📤 Syncing way ID: \(way.id)")
133133
let payload = way.asOSMWay()
134134
do {
135-
let status = try await syncWay(way: payload, exclude_gig_tags: exclude_gig_tags)
135+
let status = try await syncWay(way: payload, exclude_gig_tags: exclude_gig_tags, editedTags: way.tags.toDictionary())
136136
if status.result {
137137
DispatchQueue.main.async {
138138
self.dbInstance.assignChangesetId(obj: key, changesetId: 0, updatedVersion: status.version)
@@ -288,7 +288,7 @@ class DatasyncManager {
288288
}
289289

290290
// utility function to act as substitute for osmConnection functions
291-
func updateNode(node: OSMNode, exclude_gig_tags: Bool = false) async throws -> Int {
291+
func updateNode(node: OSMNode, exclude_gig_tags: Bool) async throws -> Int {
292292
var localNode = node
293293
let nodeBodyString = localNode.toPayload(exclude_gig_tags: exclude_gig_tags)
294294
let changesetUploadBody = "<osmChange version=\"0.6\" generator=\"GIG Change generator\">" + nodeBodyString + "</osmChange>"
@@ -356,7 +356,7 @@ class DatasyncManager {
356356
}
357357
}
358358

359-
func updateWay2(way: OSMWay, exclude_gig_tags: Bool = false) async throws -> Int {
359+
func updateWay2(way: OSMWay, exclude_gig_tags: Bool, editedTags: [String : String]) async throws -> Int {
360360
var localWay = way
361361
let wayId = "\(localWay.id)"
362362
var updatedResult: Int = -1
@@ -367,19 +367,24 @@ class DatasyncManager {
367367
switch error {
368368
case .conflict:
369369
let updatedWay = try await fetchway2(wayId: wayId)
370-
var mergedWay = self.mergeWays(localWay: localWay, latestWay: updatedWay)
371-
print("Local way")
372-
print(localWay)
373-
print("Merged way")
374-
print(mergedWay)
375-
return try await updateWay(way: mergedWay, exclude_gig_tags: exclude_gig_tags)
370+
if let mergedWay = self.mergeWays(localWay: localWay, latestWay: updatedWay, exclude_gig_tags: exclude_gig_tags, editedTags: editedTags) {
371+
print("Local way")
372+
print(localWay)
373+
print("Merged way")
374+
print(mergedWay)
375+
return try await updateWay(way: mergedWay, exclude_gig_tags: exclude_gig_tags)
376+
} else {
377+
print("Undo operation is not possible")
378+
return updatedWay.version
379+
}
380+
376381
default:
377382
throw error
378383
}
379384
}
380385
}
381386

382-
func updateNode2(node: OSMNode, exclude_gig_tags: Bool) async throws -> Int {
387+
func updateNode2(node: OSMNode, exclude_gig_tags: Bool, editedTags: [String : String]) async throws -> Int {
383388
var localNode = node
384389

385390
let nodeId = "\(localNode.id)"
@@ -396,13 +401,18 @@ class DatasyncManager {
396401
SyncLogger.shared.logStep("Fetching node due to conflict")
397402
let fetchedResult = try await fetchNode2(nodeId: "\(localNode.id)")
398403

399-
var mergedNode = self.mergeNodes(localNode: localNode, latestNode: fetchedResult)
400-
print("Local Node:")
401-
print(localNode)
402-
print("Merged Node:")
403-
print(mergedNode)
404-
SyncLogger.shared.logStep("Nodes fetched and merged")
405-
return try await updateNode(node: mergedNode)
404+
if let mergedNode = self.mergeNodes(localNode: localNode, latestNode: fetchedResult, exclude_gig_tags: exclude_gig_tags, editedTags: editedTags) {
405+
print("Local Node:")
406+
print(localNode)
407+
print("Merged Node:")
408+
print(mergedNode)
409+
SyncLogger.shared.logStep("Nodes fetched and merged")
410+
return try await updateNode(node: mergedNode, exclude_gig_tags: exclude_gig_tags)
411+
} else {
412+
print("Undo operation is not possible")
413+
return fetchedResult.version
414+
}
415+
406416
default:
407417
throw error
408418
}
@@ -411,19 +421,78 @@ class DatasyncManager {
411421
}
412422

413423

414-
func mergeWays(localWay: OSMWay, latestWay: OSMWay) -> OSMWay {
424+
func mergeTagsForUndo(originalTags: [String : String], edited: [String : String], serverTags: [String : String]) -> [String : String]? {
425+
var resultTags: [String: String] = [:]
426+
print("mergeTagsForUndo originalTags \(originalTags) \n edited \(edited) \n serverTags \(serverTags)")
427+
for (key, value) in edited {
428+
if let orgValue = originalTags[key] {
429+
if let serverVal = serverTags[key] {
430+
if orgValue != serverVal, value != serverVal {
431+
return nil
432+
}
433+
} else {
434+
return nil
435+
}
436+
} else {
437+
if let serverVal = serverTags[key], value != serverVal {
438+
return nil
439+
}
440+
}
441+
}
442+
443+
let unionKeys = Set(originalTags.keys).union(Set(serverTags.keys))
444+
445+
for key in unionKeys {
446+
if let serverValue = serverTags[key] {
447+
if let editValue = edited[key] {
448+
if editValue == serverValue {
449+
if let originalValue = originalTags[key] {
450+
resultTags[key] = originalValue
451+
continue
452+
}
453+
continue
454+
}
455+
}
456+
resultTags[key] = serverValue
457+
} else {
458+
resultTags.removeValue(forKey: key)
459+
}
460+
}
461+
resultTags.removeValue(forKey: "ext:gig_last_updated")
462+
resultTags.removeValue(forKey: "ext:gig_complete")
463+
print("mergeTagsForUndo resultTags \(resultTags)")
464+
return resultTags
465+
}
466+
467+
func mergeWays(localWay: OSMWay, latestWay: OSMWay, exclude_gig_tags: Bool, editedTags: [String : String]) -> OSMWay? {
415468
var mergedWay = latestWay
416-
for (key, value) in localWay.tags {
417-
mergedWay.tags[key] = value
418-
}
469+
if exclude_gig_tags {
470+
if let resultTags = mergeTagsForUndo(originalTags: localWay.tags, edited: editedTags, serverTags: latestWay.tags) {
471+
mergedWay.tags = resultTags
472+
} else {
473+
return nil
474+
}
475+
} else {
476+
for (key, value) in localWay.tags {
477+
mergedWay.tags[key] = value
478+
}
479+
}
419480
mergedWay.changeset = localWay.changeset
420481
return mergedWay
421482
}
422483

423-
func mergeNodes(localNode: OSMNode, latestNode: OSMNode) -> OSMNode {
484+
func mergeNodes(localNode: OSMNode, latestNode: OSMNode, exclude_gig_tags: Bool, editedTags: [String : String]) -> OSMNode? {
424485
var mergedNode = latestNode
425-
for (key, value) in localNode.tags {
426-
mergedNode.tags[key] = value
486+
if exclude_gig_tags {
487+
if let resultTags = mergeTagsForUndo(originalTags: localNode.tags, edited: editedTags, serverTags: latestNode.tags) {
488+
mergedNode.tags = resultTags
489+
} else {
490+
return nil
491+
}
492+
} else {
493+
for (key, value) in localNode.tags {
494+
mergedNode.tags[key] = value
495+
}
427496
}
428497
mergedNode.changeset = localNode.changeset
429498
return mergedNode
@@ -500,7 +569,7 @@ class DatasyncManager {
500569
Syncs the node along with the updated
501570
*/
502571
@MainActor
503-
func syncNode(node: OSMNode, exclude_gig_tags: Bool) async throws -> (result:Bool, version: Int) {
572+
func syncNode(node: OSMNode, exclude_gig_tags: Bool, editedTags: [String : String]) async throws -> (result:Bool, version: Int) {
504573
var localNode = node
505574

506575
SyncLogger.shared.logStep("Open Changeset")
@@ -513,7 +582,7 @@ class DatasyncManager {
513582
localNode.changeset = changesetID
514583

515584
//Step 2: Update Node
516-
let newVersion = try await updateNode2(node: localNode, exclude_gig_tags: exclude_gig_tags)
585+
let newVersion = try await updateNode2(node: localNode, exclude_gig_tags: exclude_gig_tags, editedTags: editedTags)
517586
localNode.version = newVersion
518587
DispatchQueue.main.async {
519588
self.dbInstance.updateNodeVersion(nodeId: String(localNode.id), version: newVersion)
@@ -552,7 +621,7 @@ class DatasyncManager {
552621
}
553622

554623
@MainActor
555-
func syncWay(way: OSMWay, exclude_gig_tags: Bool = false) async throws -> (result: Bool, version: Int) {
624+
func syncWay(way: OSMWay, exclude_gig_tags: Bool, editedTags: [String : String]) async throws -> (result: Bool, version: Int) {
556625
var localWay = way
557626

558627
do {
@@ -561,7 +630,7 @@ class DatasyncManager {
561630

562631
localWay.changeset = changesetID
563632

564-
let newVersion = try await updateWay2(way: localWay, exclude_gig_tags: exclude_gig_tags)
633+
let newVersion = try await updateWay2(way: localWay, exclude_gig_tags: exclude_gig_tags, editedTags: editedTags)
565634

566635
localWay.version = newVersion
567636

GoInfoGame/GoInfoGame/quests/QuestProtocols.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ class QuestBase {
4545
var result: (result: Bool, version: Int) = (false, -1)
4646
switch storedElementType {
4747
case .node:
48-
result = try await DatasyncManager.shared.syncNode(node: changeSet.asOSMNode(isUndo: true), exclude_gig_tags: true)
48+
result = try await DatasyncManager.shared.syncNode(node: changeSet.asOSMNode(isUndo: true), exclude_gig_tags: true, editedTags: changeSet.tags.toDictionary())
4949
case .way:
50-
result = try await DatasyncManager.shared.syncWay(way: changeSet.asOSMWay(isUndo: true), exclude_gig_tags: true)
50+
result = try await DatasyncManager.shared.syncWay(way: changeSet.asOSMWay(isUndo: true), exclude_gig_tags: true, editedTags: changeSet.tags.toDictionary())
5151
case .unknown:
5252
print("❌ Undo failed: Element type not found")
5353
}

0 commit comments

Comments
 (0)