Commit b59f60ee501f9d4c2c8b0d9990a6ffd2507474ce

Authored by liushiyu
1 parent 47a2e13e

排序判断逻辑

metaCode/Classes/Config/CNLiveConfigUserInfo.swift
@@ -109,10 +109,123 @@ class UserInfoManager: NSObject { @@ -109,10 +109,123 @@ class UserInfoManager: NSObject {
109 static public func clearUserInfo() { 109 static public func clearUserInfo() {
110 UserDefaults.standard.removeObject(forKey: "mateCode_userInfo") 110 UserDefaults.standard.removeObject(forKey: "mateCode_userInfo")
111 UserInfoManager.shared._userInfo = nil 111 UserInfoManager.shared._userInfo = nil
  112 + StandSortManager.removeStandSort()
112 if UserDefaults.standard.synchronize() { 113 if UserDefaults.standard.synchronize() {
113 print("用户信息删除成功") 114 print("用户信息删除成功")
114 } 115 }
115 } 116 }
116 } 117 }
117 118
  119 +class StandSortManager: NSObject {
  120 +
  121 + static let shared = StandSortManager()
  122 +
  123 + //根据用户信息设置key
  124 + static let sort_key: String = "mateCode_stand_sort_key_"+UserInfoManager.shared.userInfo.uid
  125 + fileprivate var _indexs : Array<String>?
  126 + private(set) var indexs: Array<String> {
  127 + set {
  128 + _indexs = newValue
  129 + }
  130 +
  131 + get {
  132 + return []
  133 + }
  134 + }
  135 +
  136 + /// 存储排序信息
  137 + /// - Parameter indexs: 排序的index
  138 + static private func cacheStandSort(indexs: NSArray) {
  139 + StandSortManager.shared._indexs = indexs as? Array<String>
  140 + UserDefaults.standard.set(indexs, forKey: sort_key)
  141 + if UserDefaults.standard.synchronize() {
  142 + print("排序信息存储成功")
  143 + }
  144 + }
  145 +
  146 + /// 获取排序信息
  147 + /// - Returns: 返回信息
  148 + static private func readStandSort() -> NSArray {
  149 + let indexs = UserDefaults.standard.object(forKey: sort_key)
  150 + if indexs == nil && (indexs as! NSArray).count == 0 {
  151 + print("获取排序信息失败")
  152 + return []
  153 + }
  154 + StandSortManager.shared._indexs = indexs as? Array<String>
  155 + return indexs as! NSArray
  156 + }
  157 +
  158 + /// 移除排序信息
  159 + static public func removeStandSort() {
  160 + UserDefaults.standard.removeObject(forKey: sort_key)
  161 + StandSortManager.shared._indexs = []
  162 + if UserDefaults.standard.synchronize() {
  163 + print("排序信息删除成功")
  164 + }
  165 + }
  166 +
  167 + /// 对获取到的全部数据进行排序
  168 + /// - Parameter stands: 获取到的数据
  169 + /// - Returns: 返回 //<StandListModel>
  170 + static public func sortAllListData(stands: NSArray) -> NSArray {
  171 + let have_id_auths = StandSortManager.readStandSort()
  172 + if have_id_auths.count == 0 {
  173 + return stands
  174 + }
  175 + print("allList接口里面===>\(have_id_auths)")
  176 + let have_auths = NSMutableArray()
  177 + let no_auths = NSMutableArray()
  178 + for item in stands {
  179 + let listModel = item as! StandListModel
  180 + //这里需要及时去刷新认证状态 如果没有及时刷新这里回出现已经认证的状态不会进行排序
  181 + listModel.auth && have_id_auths.contains(listModel.id) ? have_auths.add(listModel) : no_auths.add(listModel)
  182 + }
  183 + let tempArray = NSMutableArray()
  184 + for item in have_auths {
  185 + let standModel = item as! StandListModel
  186 + let old_index = have_auths.index(of: standModel)
  187 + let new_index = have_id_auths.index(of: standModel.id)
  188 + if old_index != new_index {
  189 + swap(&have_auths[new_index], &have_auths[old_index])
  190 + }
  191 + }
  192 + tempArray.addObjects(from: have_auths as! [Any])
  193 + tempArray.addObjects(from: no_auths as! [Any])
  194 + return tempArray
  195 + }
  196 +
  197 +
  198 + /// 对已经获取到的认证身份进行排序
  199 + /// - Parameter auths: 获取到的数据
  200 + /// - Returns: 返回 //<MineAuthListModel>
  201 + static public func sortMyListData(auths: NSArray) -> NSArray {
  202 + let have_id_auths = StandSortManager.readStandSort()
  203 + if have_id_auths.count == 0 {
  204 + return auths
  205 + }
  206 + print("myList接口里面===>\(have_id_auths)")
  207 + let have_auths = NSMutableArray.init(array: auths)
  208 + for item in auths {
  209 + let standModel = item as! MineAuthListModel
  210 + let old_index = have_auths.index(of: standModel)
  211 + let new_index = have_id_auths.index(of: standModel.identityId)
  212 + if old_index != new_index {
  213 + swap(&have_auths[new_index], &have_auths[old_index])
  214 + }
  215 + }
  216 + return have_auths
  217 + }
  218 +
  219 + /// 更新之后重新插入
  220 + /// - Parameter indexs: 所以
  221 + static public func insertSortData(indexs: NSArray) {
  222 + if (indexs.count > 0) {
  223 + StandSortManager.shared._indexs = []
  224 + StandSortManager.removeStandSort()
  225 + StandSortManager.cacheStandSort(indexs: indexs)
  226 + }
  227 + }
  228 +
  229 +}
  230 +
118 231
metaCode/Classes/Config/Database/CNLiveSaveAuthDB.swift
@@ -21,7 +21,7 @@ class CNLiveSaveAuthDB : NSObject{ @@ -21,7 +21,7 @@ class CNLiveSaveAuthDB : NSObject{
21 //重新init方法为私有,不让外部调用 21 //重新init方法为私有,不让外部调用
22 private override init() { 22 private override init() {
23 //数据库地址 23 //数据库地址
24 - let filePath = NSHomeDirectory() + "/Documents/DB/CNLiveAuthListTable.db" 24 + let filePath = NSHomeDirectory() + "/Documents/DB"+UserInfoManager.shared.userInfo.uid+"/CNLiveAuthListTable.db"
25 database = Database(at: filePath) 25 database = Database(at: filePath)
26 26
27 super.init() 27 super.init()
@@ -48,6 +48,10 @@ class CNLiveSaveAuthDB : NSObject{ @@ -48,6 +48,10 @@ class CNLiveSaveAuthDB : NSObject{
48 func insertObjects(objects: [MineAuthListModel]) { 48 func insertObjects(objects: [MineAuthListModel]) {
49 if objects.count > 0 { 49 if objects.count > 0 {
50 do{ 50 do{
  51 + for model in objects {
  52 + let m = model
  53 + print("插入时的数据结构===>\(m.identityId)")
  54 + }
51 try database.insert(objects, intoTable: CNLiveAuthListTableName) 55 try database.insert(objects, intoTable: CNLiveAuthListTableName)
52 }catch{ 56 }catch{
53 print("增加一条数据失败") 57 print("增加一条数据失败")
@@ -137,7 +141,8 @@ class CNLiveSaveAuthDB : NSObject{ @@ -137,7 +141,8 @@ class CNLiveSaveAuthDB : NSObject{
137 let allData: [MineAuthListModel] = try database.getObjects(fromTable: CNLiveAuthListTableName) 141 let allData: [MineAuthListModel] = try database.getObjects(fromTable: CNLiveAuthListTableName)
138 let tempArray = NSMutableArray.init() 142 let tempArray = NSMutableArray.init()
139 for item in allData { 143 for item in allData {
140 - tempArray.add("\(item.identityId)") 144 + print("数据库查找之后数据==>\(item.identityId)")
  145 + tempArray.add(item.identityId)
141 } 146 }
142 return tempArray as! Array<String> 147 return tempArray as! Array<String>
143 }catch{ 148 }catch{
metaCode/Classes/Config/Database/CNLiveSaveStandDB.swift
@@ -20,7 +20,7 @@ class CNLiveSaveStandDB: NSObject { @@ -20,7 +20,7 @@ class CNLiveSaveStandDB: NSObject {
20 //重新init方法为私有,不让外部调用 20 //重新init方法为私有,不让外部调用
21 private override init() { 21 private override init() {
22 //数据库地址 22 //数据库地址
23 - let filePath = NSHomeDirectory() + "/Documents/DB/CNLiveStandListTableName.db" 23 + let filePath = NSHomeDirectory() + "/Documents/DB"+UserInfoManager.shared.userInfo.uid+"/CNLiveStandListTableName.db"
24 database = Database(at: filePath) 24 database = Database(at: filePath)
25 25
26 super.init() 26 super.init()
metaCode/Classes/Main/MinePage/Controller/CNLiveMineAddInfoViewController.swift
@@ -321,8 +321,13 @@ extension CNLiveMineAddInfoViewController { @@ -321,8 +321,13 @@ extension CNLiveMineAddInfoViewController {
321 to destinationIndexPath: IndexPath) { 321 to destinationIndexPath: IndexPath) {
322 objc_sync_enter(self) 322 objc_sync_enter(self)
323 swap(&dataArray[sourceIndexPath.row], &dataArray[destinationIndexPath.row]) 323 swap(&dataArray[sourceIndexPath.row], &dataArray[destinationIndexPath.row])
324 - CNLiveSaveAuthDB.shared.deleteAllObjects()  
325 - CNLiveSaveAuthDB.shared.insertObjects(objects: dataArray as! [MineAuthListModel]) 324 + let tempArray = NSMutableArray()
  325 + for model in dataArray {
  326 + let m = model as! MineAuthListModel
  327 + tempArray.add(m.identityId)
  328 + }
  329 + print("索引存储的key=>\(tempArray)")
  330 + StandSortManager.insertSortData(indexs: tempArray)
326 objc_sync_exit(self) 331 objc_sync_exit(self)
327 } 332 }
328 } 333 }
metaCode/Classes/Main/MinePage/View/CNLiveMineBodyListView.swift
@@ -51,6 +51,7 @@ class MineBodyOneListViewCell : UITableViewCell { @@ -51,6 +51,7 @@ class MineBodyOneListViewCell : UITableViewCell {
51 tipLabel.textColor = HexColor("#999999") 51 tipLabel.textColor = HexColor("#999999")
52 tipLabel.text = "您暂未进行身份认证" 52 tipLabel.text = "您暂未进行身份认证"
53 tipLabel.font = Font_13 53 tipLabel.font = Font_13
  54 + tipLabel.isHidden = true
54 return tipLabel 55 return tipLabel
55 }() 56 }()
56 57
@@ -67,6 +68,35 @@ class MineBodyOneListViewCell : UITableViewCell { @@ -67,6 +68,35 @@ class MineBodyOneListViewCell : UITableViewCell {
67 mainView.addSubview(lookBtn) 68 mainView.addSubview(lookBtn)
68 69
69 setupConstraints() 70 setupConstraints()
  71 +
  72 +
  73 + let tempArray = StandSortManager.sortMyListData(auths: CNLiveSaveAuthDB.shared.searchAllObject() as NSArray) as! [MineAuthListModel]
  74 + if tempArray.count == 0 {
  75 + tipLabel.isHidden = false
  76 + }else{
  77 + for item in tempArray {
  78 + let authModel = item
  79 +// setupWithIconsView(authModel: authModel, index: index)
  80 + }
  81 + }
  82 + }
  83 +
  84 + private func setupWithIconsView(authModel: MineAuthListModel,index: NSInteger) {
  85 +
  86 + let iconView = UIImageView.init()
  87 + iconView.layer.cornerRadius = 10
  88 + iconView.layer.masksToBounds = true
  89 + iconView.clipsToBounds = true
  90 + iconView.contentMode = .scaleToFill
  91 + iconView.backgroundColor = .white
  92 + iconView.kf.setImage(with: URL(string: authModel.icon ?? ""), placeholder: UIImage.imageWithColor(color: HexColor("#f9f9f9")!, size: CGSize(width: 20, height: 20)))
  93 + mainView.addSubview(iconView)
  94 + iconView.snp.makeConstraints { make in
  95 + make.centerY.equalToSuperview()
  96 + make.left.equalToSuperview().offset(10+(20 * index)-(index>1 ? 3:0))
  97 + make.size.equalTo(20)
  98 + }
  99 +
70 } 100 }
71 101
72 required init?(coder: NSCoder) { 102 required init?(coder: NSCoder) {
metaCode/Classes/Main/MinePage/View/CNLiveMineSubBodyListView.swift
@@ -157,7 +157,7 @@ class MineStandInfoTableViewCell: UITableViewCell { @@ -157,7 +157,7 @@ class MineStandInfoTableViewCell: UITableViewCell {
157 public func setupWithAuthDataSource(icon: String, name: String,number: String) { 157 public func setupWithAuthDataSource(icon: String, name: String,number: String) {
158 iconView.kf.setImage(with: URL(string: icon), placeholder: UIImage.imageWithColor(color: HexColor("#f9f9f9")!, size: CGSize(width: 50, height: 50))) 158 iconView.kf.setImage(with: URL(string: icon), placeholder: UIImage.imageWithColor(color: HexColor("#f9f9f9")!, size: CGSize(width: 50, height: 50)))
159 titleLabel.text = name 159 titleLabel.text = name
160 - numberLabel.text = number 160 + numberLabel.text = "编号:\(number)"
161 } 161 }
162 162
163 public func setupWithMessageDataSource(icon: String, name: String,number: String, time: String) { 163 public func setupWithMessageDataSource(icon: String, name: String,number: String, time: String) {
metaCode/Classes/Main/MinePage/ViewModel/CNLiveMineBaseModel.swift
@@ -181,12 +181,13 @@ final class StandListModel: BaseModel, TableCodable { @@ -181,12 +181,13 @@ final class StandListModel: BaseModel, TableCodable {
181 181
182 enum CodingKeys: String, CodingTableKey { 182 enum CodingKeys: String, CodingTableKey {
183 typealias Root = StandListModel 183 typealias Root = StandListModel
184 - static let objectRelationalMapping = TableBinding(CodingKeys.self){ 184 + static let objectRelationalMapping = TableBinding(CodingKeys.self)
  185 + {
185 //设置表的主键key为id,用来区分数据唯一性, 如果id为int类型,可以按实现按顺序递增 186 //设置表的主键key为id,用来区分数据唯一性, 如果id为int类型,可以按实现按顺序递增
186 - BindColumnConstraint(id, isPrimary: true) 187 + BindColumnConstraint(id, isPrimary: true, isAutoIncrement: true)
187 } 188 }
188 - case id //不修改数据库字段名,和属性名保持一直  
189 - case name //不修改数据库字段名,和属性名保持一直 189 + case id
  190 + case name
190 case enable 191 case enable
191 case createTime 192 case createTime
192 case createTimeString 193 case createTimeString
@@ -263,10 +264,12 @@ final class MineAuthListModel: BaseModel , TableCodable { @@ -263,10 +264,12 @@ final class MineAuthListModel: BaseModel , TableCodable {
263 var userStatus: Int = 0 264 var userStatus: Int = 0
264 265
265 enum CodingKeys: String, CodingTableKey { 266 enum CodingKeys: String, CodingTableKey {
  267 +
266 typealias Root = MineAuthListModel 268 typealias Root = MineAuthListModel
267 - static let objectRelationalMapping = TableBinding(CodingKeys.self){ 269 + static let objectRelationalMapping = TableBinding(CodingKeys.self)
  270 + {
268 //设置表的主键key为id,用来区分数据唯一性, 如果id为int类型,可以按实现按顺序递增 271 //设置表的主键key为id,用来区分数据唯一性, 如果id为int类型,可以按实现按顺序递增
269 - BindColumnConstraint(identityId, isPrimary: true) 272 + BindColumnConstraint(identityId, isPrimary: true, isAutoIncrement: true)
270 } 273 }
271 case identityId //不修改数据库字段名,和属性名保持一直 274 case identityId //不修改数据库字段名,和属性名保持一直
272 case name //不修改数据库字段名,和属性名保持一直 275 case name //不修改数据库字段名,和属性名保持一直
metaCode/Classes/Main/MinePage/ViewModel/CNLiveMineViewModel.swift
@@ -265,46 +265,33 @@ class CNLiveMineViewModel: NSObject { @@ -265,46 +265,33 @@ class CNLiveMineViewModel: NSObject {
265 let errorCode = "\(resp["errorCode"] ?? "0")" 265 let errorCode = "\(resp["errorCode"] ?? "0")"
266 if (errorCode == "0") { 266 if (errorCode == "0") {
267 let listModel = dictionaryToModel(resp as! [String : Any], StandListBaseModel.self,"data") as! StandListBaseModel 267 let listModel = dictionaryToModel(resp as! [String : Any], StandListBaseModel.self,"data") as! StandListBaseModel
268 -  
269 - if CNLiveSaveStandDB.shared.searchAllObject().count > 0 {  
270 - //第一页  
271 - if page == 1 {  
272 - let have_id_auths = CNLiveSaveAuthDB.shared.searchAllObjectId()  
273 - let have_auths = NSMutableArray()  
274 - let no_auths = NSMutableArray()  
275 - for item in listModel.list {  
276 - //这里需要及时去刷新认证状态 如果没有及时刷新这里回出现已经认证的状态不会进行排序  
277 - item.auth && have_id_auths.contains("\(item.id)") ? have_auths.add(item) : no_auths.add(item)  
278 - }  
279 - let tempArray = NSMutableArray()  
280 - for item in have_auths {  
281 - let standModel = item as! StandListModel  
282 - let old_index = have_auths.index(of: standModel)  
283 - let new_index = have_id_auths.firstIndex(of: "\(standModel.id)")  
284 - if old_index != new_index {  
285 - swap(&have_auths[new_index!], &have_auths[old_index])  
286 - }  
287 - }  
288 - tempArray.addObjects(from: have_auths as! [Any])  
289 - tempArray.addObjects(from: no_auths as! [Any])  
290 - listModel.list = tempArray as! [StandListModel]  
291 - CNLiveSaveStandDB.shared.deleteAllObjects()  
292 - CNLiveSaveStandDB.shared.insertObjects(objects: listModel.list)  
293 - }else{  
294 -  
295 - }  
296 - }else{ 268 + if page == 1 && listModel.list.count > 0 {
297 CNLiveSaveStandDB.shared.insertObjects(objects: listModel.list) 269 CNLiveSaveStandDB.shared.insertObjects(objects: listModel.list)
298 } 270 }
299 -  
300 - 271 + listModel.list = StandSortManager.sortAllListData(stands: listModel.list as NSArray) as! [StandListModel]
301 resultBlock(listModel,.success) 272 resultBlock(listModel,.success)
302 } else { 273 } else {
303 - showMessage(message: resp["errorMessage"] as! String)  
304 - resultBlock(NSNull(),.failed) 274 + let tempArray = CNLiveSaveStandDB.shared.searchAllObject()
  275 + if tempArray.count > 0 {
  276 + let listModel = StandListBaseModel.init()
  277 + listModel.pageNum = page
  278 + listModel.total = page
  279 + listModel.list = StandSortManager.sortAllListData(stands: tempArray as NSArray) as! [StandListModel]
  280 + resultBlock(listModel,.failed)
  281 + }else{
  282 + showMessage(message: resp["errorMessage"] as! String)
  283 + resultBlock(NSNull(),.failed)
  284 + }
305 } 285 }
306 } else { 286 } else {
307 - if page > 1 { 287 + let tempArray = CNLiveSaveStandDB.shared.searchAllObject()
  288 + if tempArray.count > 0 {
  289 + let listModel = StandListBaseModel.init()
  290 + listModel.pageNum = page
  291 + listModel.total = page
  292 + listModel.list = StandSortManager.sortAllListData(stands: tempArray as NSArray) as! [StandListModel]
  293 + resultBlock(listModel,.failed)
  294 + }else{
308 if CNLiveNetworking.isNetworking() { 295 if CNLiveNetworking.isNetworking() {
309 showMessage(message: "获取失败") 296 showMessage(message: "获取失败")
310 resultBlock(NSNull(),.failed) 297 resultBlock(NSNull(),.failed)
@@ -336,34 +323,33 @@ class CNLiveMineViewModel: NSObject { @@ -336,34 +323,33 @@ class CNLiveMineViewModel: NSObject {
336 let errorCode = "\(resp["errorCode"] ?? "0")" 323 let errorCode = "\(resp["errorCode"] ?? "0")"
337 if (errorCode == "0") { 324 if (errorCode == "0") {
338 let listModel = dictionaryToModel(resp as! [String : Any], MineAuthListBaseModel.self,"data") as! MineAuthListBaseModel 325 let listModel = dictionaryToModel(resp as! [String : Any], MineAuthListBaseModel.self,"data") as! MineAuthListBaseModel
339 - if page == 1 {  
340 - let have_id_auths = CNLiveSaveAuthDB.shared.searchAllObjectId()  
341 - if have_id_auths.count > 0 {  
342 - let tempArray = NSMutableArray.init(array: listModel.list)  
343 - for item in tempArray {  
344 - if (have_id_auths.contains("\((item as! MineAuthListModel).identityId)")) {  
345 -// tempArray_have.add(item)  
346 - }else{  
347 -// tempArray_no.add(item)  
348 - }  
349 - }  
350 -// listModel.list = tempArray as! [MineAuthListModel]  
351 - }else{  
352 - //本地没值 不进行处理  
353 - }  
354 - CNLiveSaveAuthDB.shared.deleteAllObjects() 326 + if page == 1 && listModel.list.count > 0 {
355 CNLiveSaveAuthDB.shared.insertObjects(objects: listModel.list) 327 CNLiveSaveAuthDB.shared.insertObjects(objects: listModel.list)
356 - } else {  
357 - //多条数据  
358 } 328 }
359 - 329 + listModel.list = StandSortManager.sortMyListData(auths: listModel.list as NSArray) as! [MineAuthListModel]
360 resultBlock(listModel,.success) 330 resultBlock(listModel,.success)
361 } else { 331 } else {
362 - showMessage(message: resp["errorMessage"] as! String)  
363 - resultBlock(NSNull(),.failed) 332 + let tempArray = CNLiveSaveAuthDB.shared.searchAllObject()
  333 + if tempArray.count > 0 {
  334 + let listModel = MineAuthListBaseModel.init()
  335 + listModel.pageNum = page
  336 + listModel.total = page
  337 + listModel.list = StandSortManager.sortMyListData(auths: tempArray as NSArray) as! [MineAuthListModel]
  338 + resultBlock(listModel,.failed)
  339 + }else{
  340 + showMessage(message: resp["errorMessage"] as! String)
  341 + resultBlock(NSNull(),.failed)
  342 + }
364 } 343 }
365 } else { 344 } else {
366 - if page > 1 { 345 + let tempArray = CNLiveSaveAuthDB.shared.searchAllObject()
  346 + if tempArray.count > 0 {
  347 + let listModel = MineAuthListBaseModel.init()
  348 + listModel.pageNum = page
  349 + listModel.total = page
  350 + listModel.list = StandSortManager.sortMyListData(auths: tempArray as NSArray) as! [MineAuthListModel]
  351 + resultBlock(listModel,.failed)
  352 + }else{
367 if CNLiveNetworking.isNetworking() { 353 if CNLiveNetworking.isNetworking() {
368 showMessage(message: "获取失败") 354 showMessage(message: "获取失败")
369 resultBlock(NSNull(),.failed) 355 resultBlock(NSNull(),.failed)
metaCode/Classes/Other/AppDelegate.swift
@@ -17,6 +17,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { @@ -17,6 +17,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
17 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 18
19 // Override point for customization after application launch. 19 // Override point for customization after application launch.
  20 +
20 21
21 //设置APP环境 22 //设置APP环境
22 CNLiveEnvironmentManager.shared.setupEnvironment(environment: .development) 23 CNLiveEnvironmentManager.shared.setupEnvironment(environment: .development)
@@ -59,6 +60,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { @@ -59,6 +60,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
59 CNLiveNetworking.setResponseSerializerType(.JSON) 60 CNLiveNetworking.setResponseSerializerType(.JSON)
60 CNLiveNetworking.setupBaseURL(APPLoginHost) 61 CNLiveNetworking.setupBaseURL(APPLoginHost)
61 } 62 }
  63 +
  64 +
62 65
63 66
64 } 67 }