Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexanderBollbach/7ccf81c17465caa70a8c751e34853b25 to your computer and use it in GitHub Desktop.
Save AlexanderBollbach/7ccf81c17465caa70a8c751e34853b25 to your computer and use it in GitHub Desktop.
a crazy over the top graph i made to model project types in my drawing app
//import UIKit
//import ComposableArchitecture
//
//enum RelationType: String, Hashable, Codable {
// case selected
// case child
// case soloed
//}
//
//protocol GraphType {
// var graphType: String { get }
//}
//
//struct Node: Hashable, Codable {
// let id: UUID
// var value: NodeValue
//}
//
//extension Node: GraphType {
// var graphType: String {
// value.graphType
// }
//}
//
//struct Relation: Hashable, Codable {
//
// let from: UUID
// let to: UUID
//
// let type: RelationType
//
// var weight: Int
//
// init(from: UUID, to: UUID, type: RelationType, weight: Int = 1) {
// self.from = from
// self.to = to
// self.type = type
// self.weight = weight
// }
//}
//
//struct Graph: Equatable, Codable {
// private var nodes: Set<Node> = []
// private var relations: Set<Relation> = []
//}
//
//
//enum RelationSpec {
// case fromIds([UUID])
// case toIds([UUID])
// case relationType(RelationType)
// case weight(Int)
// case exact(Relation)
//}
//
//extension Graph {
//
// func match(relation: Relation, specs: [RelationSpec]) -> Bool {
//
// func matchFromIds(_ ids: [UUID]) -> Bool {
// ids.contains(relation.from)
// }
// func matchToIds(_ ids: [UUID]) -> Bool {
// ids.contains(relation.to)
// }
// func matchRelationType(_ value: RelationType) -> Bool {
// relation.type == value
// }
// func matchWeight(value: Int) -> Bool {
// relation.weight == value
// }
// func matchExact(value: Relation) -> Bool {
// relation == value
// }
//
// for spec in specs {
// switch spec {
// case let .fromIds(ids):
// if !matchFromIds(ids) {
// return false
// }
// case let .toIds(ids):
// if !matchToIds(ids) {
// return false
// }
// case let .relationType(value):
// if !matchRelationType(value) {
// return false
// }
// case let .weight(value):
// if !matchWeight(value: value) {
// return false
// }
// case let .exact(value):
// if !matchExact(value: value) {
// return false
// }
// }
// }
//
// return true
// }
//}
//
//extension Graph {
//
// mutating func addNode(id: UUID, value: NodeValue) {
// nodes.insert(.init(id: id, value: value))
// }
//
// mutating func updateNode<T>(
// id: UUID,
// casePath: CasePath<NodeValue, T>,
// transform: (inout T) -> Void
// ) {
//
// let newNodes: [Node] = nodes.map {
// var s = $0
// if s.id == id {
// if var val = casePath.extract(from: s.value) {
// transform(&val)
// s.value = casePath.embed(val)
// }
// }
// return s
// }
//
// self.nodes = Set(newNodes)
// }
//
// func endNodes(relations: [Relation]) -> [Node] {
// let endIds = relations.map { $0.to }
// return endIds.map { endId in nodes.first(where: { $0.id == endId })! }
// }
//
// mutating func purgeNodes(ids: [UUID]) {
//
// // remove nodes themselves
// removeNodes(ids: ids)
//
// // remove all edges to them
// removeRelations(
// matching: [
// .toIds(ids)
// ]
// )
// }
//
// func endNodeValues<T>(
// relations: [Relation],
// casePath: CasePath<NodeValue, T>
// ) -> [(UUID, T)] {
//
// relations.map { $0.to }
// .map { endId in nodes.first(where: { $0.id == endId })! }
// .map {
// guard let value = casePath.extract(from: $0.value) else { fatalError() }
// return ($0.id, value)
// }
// }
//
// func allNodes(ids: [UUID]) -> [Node] {
// nodes.filter { ids.contains($0.id) }
// }
//
// mutating func removeNodes(ids: [UUID]) {
// nodes = nodes.filter { !ids.contains($0.id) }
// }
//
// mutating func removeNodes(_ nodesToRemove: [Node]) {
// let ids = nodesToRemove.map { $0.id }
// nodes = nodes.filter { !ids.contains($0.id) }
// }
//
// mutating func removeNode(at id: UUID) {
// nodes = nodes.filter { $0.id != id }
// }
//
// func ids(type: String) -> [UUID] {
// allNodes(graphType: type).map { $0.id }
// }
//
// func allNodes(graphType: String) -> [Node] {
// nodes
// .filter { $0.graphType == graphType }
// }
//
// mutating func add(_ relation: Relation) {
// relations.insert(relation)
// }
//
// mutating func add(_ relations: Set<Relation>) {
// self.relations = self.relations.intersection(relations)
// }
//
// mutating func addNode(value: NodeValue) {
// nodes.insert(.init(id: UUID(), value: value))
// }
//
// mutating func add(node: Node) {
// nodes.insert(node)
// }
//
// func firstRelation(matching specs: [RelationSpec]) -> Relation? {
// relations.first {
// self.match(relation: $0, specs: specs)
// }
// }
//
// func allRelations(
// matching specs: [RelationSpec],
// orderedByWeight: Bool = true
// ) -> [Relation] {
//
// let rs = relations.filter {
// self.match(relation: $0, specs: specs)
// }
//
// if orderedByWeight {
// return Array(rs.sorted(by: { $0.weight < $1.weight }))
// } else {
// return Array(rs)
// }
// }
//
// mutating func removeRelations(matching specs: [RelationSpec]) {
// relations = relations.filter {
// !self.match(relation: $0, specs: specs)
// }
// }
//
// mutating func updateRelation(matching specs: [RelationSpec], transform: (inout Relation) -> Void) {
//
// let rs = relations.map { r -> Relation in
// var r = r
// if self.match(relation: r, specs: specs) {
// transform(&r)
// }
// return r
// }
//
// relations = Set(rs)
// }
//
// mutating func duplicateNode(id: UUID) {
//
// }
// }
//
//// logging
//
//extension Graph {
//
// func show() {
// nodes.forEach { self.show(node: $0) }
// relations.forEach { self.show(relation: $0) }
// }
//
// func show(node id: UUID) {
// guard let node = (nodes.first { $0.id == id }) else { fatalError() }
// show(node: node)
// }
//
// func show(node: Node) {
// print("--node--")
// print(node.id)
// print(node.value)
// print(" ")
// }
//
// func show(relation: Relation) {
// print("--relation--")
// print("type: \(relation.type)")
//
// show(node: relation.from)
// print("-------- to --------")
// show(node: relation.to)
//
// print(" ")
// }
//}
/// HERE IS SOME EXAMPLE USAGE
//
//import Foundation
//
//
//extension Project {
//
// mutating func swapLayerRight(id: UUID) {
//
// if let r1 = graph.firstRelation(matching: [.toIds([id]), .relationType(.child)]) {
// if let r2 = graph.firstRelation(matching: [.relationType(.child), .weight(r1.weight + 1)]) {
//
// graph.updateRelation(matching: [.exact(r1)]) { relation in
// relation.weight = r2.weight
// }
//
// graph.updateRelation(matching: [.exact(r2)]) { relation in
// relation.weight = r1.weight
// }
// }
// }
// }
//
// mutating func swapLayerLeft(id: UUID) {
//
// if let r1 = graph.firstRelation(matching: [.toIds([id]), .relationType(.child)]) {
// if let r2 = graph.firstRelation(matching: [.relationType(.child), .weight(r1.weight - 1)]) {
//
// graph.updateRelation(matching: [.exact(r1)]) { relation in
// relation.weight = r2.weight
// }
//
// graph.updateRelation(matching: [.exact(r2)]) { relation in
// relation.weight = r1.weight
// }
// }
// }
// }
//
// func isSoloed(layerId: UUID) -> Bool {
//
// let r = graph.firstRelation(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
//
// return r != nil
// }
//
// var hasSoloedLayers: Bool {
//
// let rs = graph.allRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
//
// return !rs.isEmpty
// }
//
// mutating func unSoloLayers() {
// graph.removeRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
// }
//
// mutating func removeSelectedLayers() {
// graph.purgeNodes(ids: selectedLayerIds)
// }
//
// mutating func toggleLayersSolo(ids: [UUID]) {
//
// for id in ids {
//
// let specs: [RelationSpec] = [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
//
// if let _ = graph.firstRelation(matching: specs) {
// graph.removeRelations(matching: specs)
// } else {
// graph.add(Relation(from: projectInfo.id, to: id, type: .selected))
// }
// }
// }
//
// mutating func selectLayerOnly(id: UUID) {
//
// graph.removeRelations(
// matching: [
// .fromIds(graph.ids(type: "ProjectInfo")),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.selected)
// ]
// )
//
// graph.add(Relation(from: projectInfo.id, to: id, type: .selected))
// }
//
// mutating func toggleLayersSelection(ids: [UUID]) {
//
// for id in ids {
//
// let specs: [RelationSpec] = [
// .fromIds([projectInfo.id]),
// .toIds([id]),
// .relationType(.selected)
// ]
//
// if let _ = graph.firstRelation(matching: specs) {
// graph.removeRelations(matching: specs)
// } else {
// graph.add(Relation(from: projectInfo.id, to: id, type: .selected))
// }
// }
// }
//
// var layers: [IdentifiedLayer] {
//
// let rs = graph.allRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.child)
// ]
// )
//
// return graph
// .endNodes(relations: rs)
// .map {
// if case let NodeValue.layer(value) = $0.value {
// return .init(id: $0.id, value: value)
// } else {
// fatalError()
// }
// }
// }
//
// var selectedLayerIds: [UUID] {
//
// let relations = graph.allRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.selected)
// ]
// )
//
// return relations.map { $0.to }
// }
//
// var soloedLayerIds: [UUID] {
//
// let relations = graph.allRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
//
// return relations.map { $0.to }
// }
//
// mutating func createAndSelectNewLayer() {
//
// let title = "Layer \(graph.allNodes(graphType: "Layer").count)"
//
// let layerId = UUID()
// graph.add(node: .init(id: layerId, value: .layer(.init(title: title))))
//
// let highestWeightedRelation = graph.allRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.child)
// ]
// ).max(by: { $1.weight > $0.weight })
//
// let nextWeight = (highestWeightedRelation?.weight ?? 0) + 1
//
// // add child relation
// graph.add(
// Relation(
// from: projectInfo.id,
// to: layerId,
// type: .child,
// weight: nextWeight
// )
// )
//
// // remove all selected relations
// graph.removeRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .relationType(.selected)
// ]
// )
//
// // add selected relation
// graph.add(
// Relation(
// from: projectInfo.id,
// to: layerId,
// type: .selected
// )
// )
// }
//
// mutating func soloSelectedLayers() {
// for layer in selectedLayerIds {
// graph.removeRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
//
// graph.add(.init(from: projectInfo.id, to: layer, type: .soloed, weight: 0))
// }
// }
//
// mutating func unsoloAllLayers() {
// graph.removeRelations(
// matching: [
// .fromIds([projectInfo.id]),
// .toIds(graph.ids(type: "Layer")),
// .relationType(.soloed)
// ]
// )
// }
//
// mutating func duplicateLayer(id: UUID) {
//
// let oldLayerId = id
//
// func nodeIds(fromId: UUID, childType: String) -> [UUID] {
// let rs = graph.allRelations(
// matching: [
// .fromIds([fromId]),
// .toIds(graph.ids(type: childType)),
// .relationType(.child)
// ]
// )
//
// return graph.endNodes(relations: rs).map { $0.id }
// }
//
// guard let projectInfoId = graph.ids(type: "ProjectInfo").first else { fatalError() }
// guard let node = graph.allNodes(ids: [id]).first, case let NodeValue.layer(oldLayer) = node.value else { fatalError() }
//
// let newLayerId = UUID()
//
// graph.add(node: Node(id: newLayerId, value: .layer(oldLayer)))
// graph.add(Relation(from: projectInfoId, to: newLayerId, type: .child, weight: self.layers.count + 1))
//
// let effectIds = nodeIds(fromId: oldLayerId, childType: "Effect")
//
// for (offset, effectId) in effectIds.enumerated() {
// guard let node = graph.allNodes(ids: [effectId]).first, case let NodeValue.effect(oldEffect) = node.value else { fatalError() }
//
// let attributeIds = nodeIds(fromId: effectId, childType: "Attribute")
//
// let newEffectId = UUID()
//
// graph.add(node: Node(id: newEffectId, value: .effect(oldEffect)))
// graph.add(.init(from: newLayerId, to: newEffectId, type: .child, weight: offset))
//
// for attributeId in attributeIds.enumerated() {
//
// guard let node = graph.allNodes(ids: [attributeId.element]).first, case let NodeValue.attribute(oldAttribute) = node.value else { fatalError() }
//
// let newAttributeId = UUID()
//
// graph.add(node: Node(id: newAttributeId, value: .attribute(oldAttribute)))
// graph.add(Relation(from: newEffectId, to: newAttributeId, type: .child, weight: attributeId.offset))
// }
// }
// }
//}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment