Skip to content

Instantly share code, notes, and snippets.

@mzaks
Last active April 27, 2016 18:10
Show Gist options
  • Select an option

  • Save mzaks/addb8ae4e7ae01316dce359969a6d95f to your computer and use it in GitHub Desktop.

Select an option

Save mzaks/addb8ae4e7ae01316dce359969a6d95f to your computer and use it in GitHub Desktop.
import Foundation
var machines : [NSURL] = []
var numberOfTicks = 0
let loadingQueues = [ // 4 cores -> 4 queues, more cores -> add more queues
dispatch_queue_create("loadingQueue1", nil),
dispatch_queue_create("loadingQueue2", nil),
dispatch_queue_create("loadingQueue3", nil),
dispatch_queue_create("loadingQueue4", nil),
]
struct CircularBuffer<T> {
private var cursor = 0
private var firstRound = true
private var buffer : [T]
init(capacity : Int, defaultValue : T){
buffer = Array.init(count: capacity, repeatedValue: defaultValue)
}
mutating func push(value: T){
buffer[cursor] = value
cursor += 1
if cursor == buffer.count {
cursor = 0
firstRound = false
}
}
var values : ArraySlice<T> {
return firstRound ? buffer[0..<cursor] : buffer[0..<buffer.count]
}
}
var fiveMinutesData : [CircularBuffer<Double>]!
func initFiveMinutesData(){
fiveMinutesData = Array.init(count: machines.count, repeatedValue: CircularBuffer(capacity:60, defaultValue:0.0))
}
func loadMachineURLs() {
let url = NSURL(string: "http://machinepark.actyx.io/api/v1/machines")
let array = try! NSJSONSerialization.JSONObjectWithData(NSData(contentsOfURL: url!)!, options: []) as! NSArray
machines = array.map { (urlPart) -> NSURL in
let fullUrlSting = (urlPart as! String).stringByReplacingOccurrencesOfString("$API_ROOT", withString:"http://machinepark.actyx.io/api/v1")
return NSURL(string:fullUrlSting)!
}
}
func tick(){
while fiveMinutesData.last?.cursor != numberOfTicks % 60 { // waiting for queues to finish
sleep(1)
}
var queueCursor = 0
for (index, url) in machines.enumerate() {
queueCursor = (queueCursor + 1) % loadingQueues.count
dispatch_async(loadingQueues[queueCursor]) {
let d = NSData(contentsOfURL: url)
if d == nil {
print("Error: \(url)")
fiveMinutesData[index].push(0) // 0 values will be ignored when calculating average
return
}
let data = try! NSJSONSerialization.JSONObjectWithData(d!, options: []) as! NSDictionary
let name = data["name"] as! String
let current = data["current"] as! NSNumber
let alert = data["current_alert"] as! NSNumber
fiveMinutesData[index].push(current.doubleValue)
if current.doubleValue >= alert.doubleValue {
let measurements = fiveMinutesData[index].values
let sum = measurements.reduce((value:0.0, elementsToIgnore:0)){sum,value in
return value == 0 ? (sum.value, sum.elementsToIgnore + 1) : (sum.value + value, sum.elementsToIgnore)
}
let mid = sum.value / Double(measurements.count - sum.elementsToIgnore)
print("Allert! \(name) is at \(current) which is above \(alert), average of last \(measurements.count - sum.elementsToIgnore) measurements is \(mid)")
}
}
}
numberOfTicks += 1
sleep(5) // collecting data at 0.2Hz best case
}
loadMachineURLs()
initFiveMinutesData()
while true {
tick()
}
//
// main.swift
// ActyxChalangeConsole
//
// Created by Maxim Zaks on 20.04.16.
// Copyright © 2016 maxim.zaks. All rights reserved.
//
import Foundation
var machines : [NSURL] = []
var numberOfTicks = 0
let loadingQueues = [
dispatch_queue_create("loadingQueue1", nil),
dispatch_queue_create("loadingQueue2", nil),
dispatch_queue_create("loadingQueue3", nil),
dispatch_queue_create("loadingQueue4", nil),
]
class CircularBuffer<T> {
private var cursor = 0
private var firstRound = true
private var buffer : [T]
init(capacity : Int, defaultValue : T){
buffer = Array.init(count: capacity, repeatedValue: defaultValue)
}
func push(value: T){
buffer[cursor] = value
cursor += 1
if cursor == buffer.count {
cursor = 0
firstRound = false
}
}
var values : ArraySlice<T> {
return firstRound ? buffer[0..<cursor] : buffer[0..<buffer.count]
}
}
var fiveMinutesData : [CircularBuffer<Double>]!
func initFiveMinutesData(){
fiveMinutesData = []
for _ in 0 ..< machines.count {
fiveMinutesData.append(CircularBuffer(capacity: 60, defaultValue: 0.0))
}
}
func loadMachineURLs() {
let url = NSURL(string: "http://machinepark.actyx.io/api/v1/machines")
let array = try! NSJSONSerialization.JSONObjectWithData(NSData(contentsOfURL: url!)!, options: []) as! NSArray
machines = array.map { (urlPart) -> NSURL in
let fullUrlSting = (urlPart as! String).stringByReplacingOccurrencesOfString("$API_ROOT", withString:"http://machinepark.actyx.io/api/v1")
return NSURL(string:fullUrlSting)!
}
}
func tick(){
while true { // waiting for queus to finish
if fiveMinutesData[fiveMinutesData.count-1].cursor == numberOfTicks % 60 &&
fiveMinutesData[fiveMinutesData.count-2].cursor == numberOfTicks % 60 &&
fiveMinutesData[fiveMinutesData.count-3].cursor == numberOfTicks % 60 &&
fiveMinutesData[fiveMinutesData.count-4].cursor == numberOfTicks % 60
{
break
}
print("!!!!!!!!!!")
sleep(1)
}
print("--------")
var queueCursor = 0
for (index, url) in machines.enumerate() {
queueCursor = (queueCursor + 1) % loadingQueues.count
let queue = loadingQueues[queueCursor]
let buffer = fiveMinutesData[index]
dispatch_async(queue) {
let t = CFAbsoluteTimeGetCurrent()
let d = NSData(contentsOfURL: url)
if d == nil {
print("Error: \(url)")
buffer.push(0) // 0 values will be ignored when calculating average
return
}
let data = try! NSJSONSerialization.JSONObjectWithData(d!, options: []) as! NSDictionary
let name = data["name"] as! String
let current = data["current"] as! NSNumber
let alert = data["current_alert"] as! NSNumber
print(index)
buffer.push(current.doubleValue)
print("\(CFAbsoluteTimeGetCurrent() - t) queue:\(queue) index: \(index)")
if current.doubleValue >= alert.doubleValue {
let measurements = buffer.values
let sum = measurements.reduce((value:0.0, elementsToIgnore:0)){sum,value in
return value == 0 ? (sum.value ,sum.elementsToIgnore + 1) : (sum.value + value ,sum.elementsToIgnore)
}
let mid = sum.value / Double(measurements.count - sum.elementsToIgnore)
print("Allert! \(name) is at \(current) which is above \(alert), average of last \(measurements.count - sum.elementsToIgnore) measurements is \(mid)")
}
}
}
numberOfTicks += 1
sleep(5) // collecting data at 0.2Hz best case
}
loadMachineURLs()
initFiveMinutesData()
while true {
tick()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment