Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

Rev 15 | Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  SyncAdapter.swift
3
//  twogetskills
4
//
5
//  Created by Efrain Yanez Recanatini on 2/24/22.
6
//
7
 
8
import Foundation
9
 
10
import Foundation
11
import Alamofire
12
import SwiftyJSON
13
 
14
class SyncAdapter
15
{
16
 
17
 
18
    private let syncDao = SyncDao.sharedInstance
19
    private var inProgress = false;
20
    private var appData = AppData.sharedInstance
21
 
22
    @objc func updateTimerForeground() {
23
        if inProgress   {
24
            return
25
        }
26
 
27
 
28
 
29
        inProgress = true
30
        let myQue = DispatchQueue(label: "syncQuueForeground")
31
        myQue.async {
32
 
33
            if self.isCheckChangesRequired()  {
34
                self.checkChanges(isForeground:true) { success in
35
                    self.inProgress = false;
36
                }
37
            } else {
38
                self.sync { success in
39
                    self.inProgress = false;
40
                }
41
            }
42
        }
43
    }
44
 
45
 
46
 
47
     func isCheckChangesRequired() -> Bool {
48
        if !appData.userUuid.isEmpty && !appData.maxDateChanges.isEmpty {
49
 
50
 
51
            let formatterService = DateFormatter()
52
            formatterService.dateFormat = Constants.FORMAT_DATETIME_SERVICE
53
            guard let lastCheckChanges = formatterService.date(from: appData.lastCheckChanges) else {
54
                let now = Date()
55
                let dateFormatter = DateFormatter()
56
                dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
57
                let dateOn = dateFormatter.string(from: now)
58
 
59
                appData.lastCheckChanges = dateOn
60
                appData.save()
61
 
62
                return false
63
 
64
            }
65
 
66
 
67
            let now = Date()
68
 
69
 
70
            let diffComponents = Calendar.current.dateComponents([.minute], from: lastCheckChanges, to: now)
71
            let minutes = diffComponents.minute!
72
 
73
 
74
            return minutes > Constants.SYNC_CHECK_CHANGES_PERIOD
75
 
76
        }
77
 
78
        return false
79
    }
80
 
81
    func checkChanges(isForeground : Bool,  completionHandler : @escaping (_ success : Bool) -> Void) {
82
 
83
        if syncDao.countPendingRecords() > 0 {
84
            completionHandler(true)
85
        }
86
 
87
 
88
        var parameters = [String : String]()
89
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_DEVICE_UUID] = appData.deviceUuid
90
 
91
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_MAX_DATE_CHANGES] = appData.maxDateChanges
92
 
93
 
94
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_IS_FOREGROUND] = isForeground ? "1" : "0"
95
 
96
 
97
 
98
 
99
        let capsuleDao = CapsuleDao.sharedInstance
100
        let capsules : [CapsuleModel] = capsuleDao.selectAll()
101
 
102
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_MAX_IDS] = String(capsules.count)
103
 
104
        var i : Int = 0
105
        while i < capsules.count {
106
 
107
            parameters["\(Constants.POST_MICROLEARNING_CHECK_CHANGES_ID)\(i+1)"] = "\(capsules[i].topicUuid)" + "|" + "\(capsules[i].uuid)"
108
 
109
            i += 1
110
        }
111
 
112
       // print(parameters)
113
 
114
        let headerSecurity : HeaderSecurity = HeaderSecurity()
115
 
116
        let headers: HTTPHeaders = [
117
            .init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
118
            .init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
119
            .init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
120
            .init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
121
            .accept(Constants.HTTP_HEADER_ACCEPT)
122
        ]
123
 
124
        AF.request(Config.URL_CHECK_CHANGES, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
125
 
126
            switch response.result {
127
                case .success:
128
                    let result = try? JSON(data: response.data!)
129
                    if result?["success"] ?? "" != false{
130
 
131
 
132
 
133
                        if result?["data"] ?? "" != "" {
134
                            let now = Date()
135
                            let dateFormatter = DateFormatter()
136
                            dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
137
                            let dateOn = dateFormatter.string(from: now)
138
 
139
                            let max_date_changes = result!["data"]["max_date_changes"].string ?? ""
140
                            let snew_capsules =  result!["data"]["new_capsules"].string ?? ""
141
 
142
 
143
                            let new_capsules = Int(snew_capsules) ?? 0
144
 
145
 
146
                            var processChanges = new_capsules > 0
147
                            processChanges = processChanges || self.appData.maxDateChanges != max_date_changes
148
 
149
                            if processChanges {
150
                                self.appData.maxDateChanges = max_date_changes
151
                            }
152
 
153
                            self.appData.lastCheckChanges = dateOn
154
                            self.appData.save()
155
 
156
                            if new_capsules > 0  {
157
                                let userinfo = ["new_capsules" : String(new_capsules), "is_foreground" : (isForeground ? "1" : "0")]
158
 
159
                                NotificationCenter.default.post(name: Constants.NOTIFICATION_NAME_COMMAND_REFRESH_CONTENT , object: self, userInfo: userinfo)
160
                            }
161
 
162
 
163
 
164
                            if result?["data"]["rating_and_comments"]  ?? "" != ""  {
165
                                let capsuleDao = CapsuleDao.sharedInstance
166
                                var capsuleModel : CapsuleModel
167
 
168
                                for ratingAndComment in result!["data"]["rating_and_comments"] {
169
 
170
                                    let uuid = ratingAndComment.1["uuid"].string ?? ""
171
                                    let total_comments = Int(ratingAndComment.1["total_comments"].string ?? "0") ?? 0
172
                                    let total_rating = Decimal(Double(ratingAndComment.1["total_rating"].string ?? "0") ?? 0)
173
 
174
 
175
                                    if !uuid.isEmpty {
176
                                        capsuleModel = capsuleDao.selectByUuid(uuid: uuid)
177
                                        capsuleModel.totalRating = total_rating
178
                                        capsuleModel.totalComments = total_comments
179
                                        capsuleDao.update(capsule: capsuleModel)
180
                                    }
181
                                }
182
                            }
183
                        }
184
                    }
185
                break
186
                case .failure:
187
                   // print("JSON = \(String(describing: Error.self))")
188
                break
189
            }
190
        }
191
 
192
        completionHandler(true)
193
    }
194
 
195
 
196
    func sync(completionHandler : @escaping (_ success : Bool) -> Void) {
197
        //print("start sync")
198
        let recordsSync = self.syncDao.selectBatch()
199
 
200
        //print(recordsSync)
201
 
202
        if recordsSync.count > 0 {
203
            var availableForOtherOperation = true;
204
            for recordSync in recordsSync
205
            {
206
                if recordSync.type == Constants.SYNC_ADAPTER_TYPE_DEVICE {
207
                    availableForOtherOperation = false
208
                    registerDevice(record: recordSync)
209
                }
210
                else if availableForOtherOperation && recordSync.type == Constants.SYNC_ADAPTER_TYPE_FCM {
211
                    availableForOtherOperation = false
212
                    registerFcm(record: recordSync)
213
                }
214
            }
215
 
216
            if(availableForOtherOperation) {
217
 
218
                var parameters = [ String: String ]()
219
                var i : Int = 0
220
                for recordSync in recordsSync
221
                {
222
                    if recordSync.type == Constants.SYNC_ADAPTER_TYPE_SYNC {
223
                        i  += 1
224
                        let keyData = Constants.POST_SYNC_BATCH_FIELD_RECORD_DATA + String(i);
225
 
226
                        let keySyncId = Constants.POST_SYNC_BATCH_FIELD_RECORD_SYNC_ID + String(i);
227
 
228
                        //print("keyData = \(keyData) keySincId = \(keySyncId)")
229
 
230
                        parameters["\(keyData)"]  = "\(recordSync.data)"
231
 
232
                        parameters["\(keySyncId)"]  =  String(recordSync.id)
233
 
234
                    }
235
                }
236
 
237
                if i > 0 {
238
                    parameters[Constants.POST_SYNC_BATCH_FIELD_MAX_RECORDS] = "\(i)"
239
                    parameters[Constants.POST_SYNC_BATCH_FIELD_DEVICE_UUID] = appData.deviceUuid
240
 
241
                    sendSyncBatch(parameters: parameters)
242
 
243
                }
244
 
245
 
246
            }
247
        }
248
        completionHandler(true)
249
    }
250
 
251
    func sendSyncBatch(parameters : [String : String])
252
    {
253
        print("Send Sync Batch  ")
254
        //print(parameters)
255
 
256
 
257
        let headers: HTTPHeaders = [
258
            .accept(Constants.HTTP_HEADER_ACCEPT)
259
        ]
260
 
261
        AF.request(Config.URL_SYNC_BATCH, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
262
 
263
 
264
 
265
            switch response.result {
266
                case .success:
267
                    let result = try? JSON(data: response.data!)
268
                    if result?["success"] ?? "" != false{
269
 
270
                        if result?["data"] != "" {
271
 
272
                            for sync in result!["data"] {
273
                                //let success = sync.1["success"].string ?? ""
274
                                let sync_id = Int(sync.1["sync_id"].string ?? "0") ?? 0
275
                                if sync_id > 0 {
276
                                    self.syncDao.remove(id: sync_id)
277
                                }
278
                            }
279
                        }
280
                    }
281
                break
282
                case .failure:
283
                   // print("JSON = \(String(describing: Error.self))")
284
                break
285
            }
286
        }
287
 
288
 
289
    }
290
 
291
    func sendSync(record: SyncModel)
292
    {
293
        let parameters = [
294
            Constants.POST_SYNC_FIELD_DEVICE_UUID: "\(appData.deviceUuid)",
295
            Constants.POST_SYNC_FIELD_DATA: "\(record.data)",
296
            Constants.POST_SYNC_FIELD_SYNC_ID: "\(record.id)"
297
        ]
298
        let headers: HTTPHeaders = [
299
            .accept(Constants.HTTP_HEADER_ACCEPT)
300
        ]
301
 
302
        AF.request(Config.URL_SYNC, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
303
 
304
            //print("Send Sync  ")
305
 
306
            switch response.result {
307
                case .success:
308
                    let result = try? JSON(data: response.data!)
309
                    if result?["success"] ?? "" != false {
310
 
311
 
312
 
313
 
314
                        let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
315
                        if sync_id > 0 {
316
                            self.syncDao.remove(id: sync_id)
317
                        }
318
                    }
319
                break
320
                case .failure:
321
                   // print("JSON = \(String(describing: Error.self))")
322
                break
323
            }
324
        }
325
    }
326
 
327
    func registerFcm(record: SyncModel) {
328
 
329
 
330
 
331
        let deviceUuid = appData.deviceUuid
332
        let parameters = [
333
            Constants.POST_FCM_FIELD_APPLICATION_ID: "\(Constants.GLOBAL_APPLICATION_ID)",
334
            Constants.POST_FCM_FIELD_DEVICE_UUID: "\(deviceUuid)",
335
            Constants.POST_FCM_FIELD_TOKEN: "\(record.data)",
336
            Constants.POST_FCM_FIELD_SYNC_ID: "\(record.id)"
337
        ]
338
 
339
        let headers: HTTPHeaders = [
340
            .accept(Constants.HTTP_HEADER_ACCEPT)
341
        ]
342
 
343
        AF.request(Config.URL_FCM, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{response in
344
 
345
            print("Send FCM")
346
 
347
            switch response.result {
348
                case .success:
349
                    let result = try? JSON(data: response.data!)
350
                    let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
351
                    if sync_id > 0 {
352
                        self.syncDao.remove(id: sync_id)
353
                    }
354
                    break
355
                case .failure:
356
                   // print("JSON = \(String(describing: Error.self))")
357
                    break
358
            }
359
        }
360
    }
361
 
362
 
363
    func registerDevice(record: SyncModel)
364
    {
365
 
366
 
367
        let version = UIDevice.current.systemVersion
368
        let model = UIDevice.current.localizedModel
369
 
370
 
371
 
372
        let parameters = [
373
            Constants.POST_DEVICE_FIELD_APPLICATION_ID: "1",
374
            Constants.POST_DEVICE_FIELD_DEVICE_UUID: "\(record.data)",
375
            Constants.POST_DEVICE_FIELD_MANUFACTURER: "Apple",
376
            Constants.POST_DEVICE_FIELD_BRAND: "Apple",
377
            Constants.POST_DEVICE_FIELD_VERSION: "\(version)",
378
            Constants.POST_DEVICE_FIELD_MODEL: "\(model)",
379
            Constants.POST_DEVICE_FIELD_PLATFORM: "Iphone",
380
            Constants.POST_DEVICE_FIELD_SYNC_ID: "\(record.id)"
381
        ]
382
 
383
        let headers: HTTPHeaders = [
384
            .accept(Constants.HTTP_HEADER_ACCEPT)
385
        ]
386
 
387
 
388
        print("URL DEVICE : \(Config.URL_DEVICE) ")
389
 
390
        AF.request(Config.URL_DEVICE, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
391
 
392
            print("Send Device: ")
393
 
394
            switch response.result {
395
                case .success:
396
                    let result = try? JSON(data: response.data!)
397
                    if result?["success"] ?? "" != false {
398
                        let aes = result?["data"]["aes"].stringValue ?? ""
399
                        let password = result?["data"]["password"].stringValue ?? ""
400
 
401
                        if !aes.isEmpty && !password.isEmpty {
402
 
403
                            self.appData.deviceAes = aes
404
                            self.appData.devicePassword = password
405
                            self.appData.save()
406
                        }
407
 
408
                        let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
409
                        if sync_id > 0 {
410
                            self.syncDao.remove(id: sync_id)
411
                        }
412
                    }
413
                break
414
                case .failure:
415
                    //print("JSON = \(String(describing: Error.self))")
416
                break
417
            }
418
        }
419
    }
420
}