Small fixes,
Graph performance issue resolved
This commit is contained in:
parent
53c7cff573
commit
237ea122e0
@ -19,5 +19,118 @@
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/GraphWindow.swift"
|
||||
timestampString = "519780364.88118"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "105"
|
||||
endingLineNumber = "105"
|
||||
landmarkName = "GraphWindow"
|
||||
landmarkType = "4">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/CollectionViewMonth.swift"
|
||||
timestampString = "519779428.097319"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "107"
|
||||
endingLineNumber = "107"
|
||||
landmarkName = "collectionView(_:didSelectItemsAt:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/CollectionViewMonth.swift"
|
||||
timestampString = "519779444.558173"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "114"
|
||||
endingLineNumber = "114"
|
||||
landmarkName = "collectionView(_:didDeselectItemsAt:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/FrequencyGraph.swift"
|
||||
timestampString = "519835152.624597"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "157"
|
||||
endingLineNumber = "157"
|
||||
landmarkName = "initView(operation:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/GraphWindow.swift"
|
||||
timestampString = "519832594.625661"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "85"
|
||||
endingLineNumber = "85"
|
||||
landmarkName = "windowDidLoad()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
condition = "item.filename! == "Downstream 666000000.hex""
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/GraphLoadOperation.swift"
|
||||
timestampString = "519832856.330867"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "32"
|
||||
endingLineNumber = "32"
|
||||
landmarkName = "main()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Graphic Analysis 2/FrequencyGraph.swift"
|
||||
timestampString = "519834850.998331"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "146"
|
||||
endingLineNumber = "146"
|
||||
landmarkName = "initView(operation:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
<EnvironmentVariable
|
||||
key = "CA_DEBUG_TRANSACTIONS"
|
||||
value = "1"
|
||||
isEnabled = "YES">
|
||||
isEnabled = "NO">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
<AdditionalOptions>
|
||||
|
||||
@ -14,7 +14,7 @@ class FileOperations: NSObject {
|
||||
// 15 in threshold indicates some error
|
||||
|
||||
static func encodeTimeStamp(stamp: String, threshold: String) -> UInt32 {
|
||||
let mappingEncode: Dictionary<String, UInt32> = ["-" : 0, "62.81": 1, "58.21": 2, "57": 3, "59.81": 4, "55.21": 5, "54": 6, "56.81": 7, "52.21": 8, "51": 9]
|
||||
let mappingEncode: Dictionary<String, UInt32> = ["-" : 0, "62.81": 1, "58.21": 2, "57": 3, "59.81": 4, "55.21": 5, "54": 6, "56.18": 7, "52.21": 8, "51": 9]
|
||||
let separated: Array<String> = stamp.components(separatedBy: ":")
|
||||
let hours: UInt32 = UInt32(separated[0])! << 16
|
||||
let minutes: UInt32 = UInt32(separated[1])! << 10
|
||||
@ -24,7 +24,7 @@ class FileOperations: NSObject {
|
||||
}
|
||||
|
||||
static func decodeTimestamp(stamp: UInt32) -> (String, String) {
|
||||
let mappingDecode: Dictionary<UInt32, String> = [0: "-", 1: "62.81", 2: "58.21", 3: "57", 4: "59.81", 5: "55.21", 6: "54", 7: "56.81", 8: "52.21", 9: "51"]
|
||||
let mappingDecode: Dictionary<UInt32, String> = [0: "-", 1: "62.81", 2: "58.21", 3: "57", 4: "59.81", 5: "55.21", 6: "54", 7: "56.18", 8: "52.21", 9: "51", 15: "-"]
|
||||
let threshold: UInt32 = stamp & 0b1111
|
||||
let seconds: UInt32 = (stamp >> 4) & 0b111111
|
||||
let minutes: UInt32 = (stamp >> 10) & 0b111111
|
||||
|
||||
@ -34,10 +34,13 @@ class FrequencyGraph: NSView {
|
||||
var cursor: NSBezierPath = NSBezierPath.init()
|
||||
// Superview
|
||||
var content: FlippedView!
|
||||
// Indicator
|
||||
var indicator: NSProgressIndicator!
|
||||
|
||||
init(upstream: Bool, frame: CGRect, superview: FlippedView) {
|
||||
init(upstream: Bool, frame: CGRect, superview: FlippedView, indicator: NSProgressIndicator) {
|
||||
super.init(frame: frame)
|
||||
self.upstream = upstream
|
||||
self.indicator = indicator
|
||||
|
||||
let tracking: NSTrackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .mouseMoved, .activeInActiveApp, .inVisibleRect], owner: self, userInfo: nil)
|
||||
self.addTrackingArea(tracking)
|
||||
@ -94,6 +97,10 @@ class FrequencyGraph: NSView {
|
||||
|
||||
func initView(operation: GraphLoadOperation) {
|
||||
// Setup Indicator
|
||||
indicator.doubleValue = 0
|
||||
indicator.isHidden = false
|
||||
indicator.minValue = 0
|
||||
indicator.maxValue = Double(data.count)
|
||||
// Zero line
|
||||
let zero: NSBezierPath = NSBezierPath()
|
||||
zero.move(to: NSPoint(x: 5, y: zeroOffset))
|
||||
@ -101,10 +108,24 @@ class FrequencyGraph: NSView {
|
||||
self.timePaths.append(zero)
|
||||
// Add data points
|
||||
var lastWasSkipped: Bool = false
|
||||
//
|
||||
var lastLossIndex: Int = 0
|
||||
for point in 0..<data.count {
|
||||
if operation.isCancelled {
|
||||
return
|
||||
}
|
||||
// Calulate offsets if start
|
||||
if point == 0 {
|
||||
// Get offset
|
||||
offset = 0
|
||||
let time: String = data[point].components(separatedBy: ";")[0]
|
||||
let hour: Int = Int(time.substring(to: time.index(time.startIndex, offsetBy: 2)))!
|
||||
let tensSeconds: Int = Int((time as NSString).substring(with: NSMakeRange(6, 1)))!
|
||||
offset = ((hour*60 + Int((time as NSString).substring(with: NSMakeRange(3, 2)))!) * 6 + tensSeconds) * 2
|
||||
// Set offset
|
||||
lastTime = offset
|
||||
lastTimeThreshold = offset
|
||||
}
|
||||
// Get values
|
||||
let level: Double? = Double(data[point].components(separatedBy: ";")[1])
|
||||
let threshold: Double? = Double(data[point].components(separatedBy: ";")[2])
|
||||
@ -116,29 +137,28 @@ class FrequencyGraph: NSView {
|
||||
if lastWasSkipped {
|
||||
restartPath(level!, threshold_level: threshold!)
|
||||
lastWasSkipped = false
|
||||
} else if point == 0 {
|
||||
// Get offset
|
||||
offset = 0
|
||||
let time: String = data[point].components(separatedBy: ";")[0]
|
||||
let hour: Int = Int(time.substring(to: time.index(time.startIndex, offsetBy: 2)))!
|
||||
let tensSeconds: Int = Int((time as NSString).substring(with: NSMakeRange(6, 1)))!
|
||||
offset = ((hour*60 + Int((time as NSString).substring(with: NSMakeRange(3, 2)))!) * 6 + tensSeconds) * 2
|
||||
// Set offset
|
||||
lastTime = offset
|
||||
lastTimeThreshold = offset
|
||||
addPath(level!, threshold_level: threshold!)
|
||||
} else {
|
||||
addPath(level!, threshold_level: threshold!)
|
||||
}
|
||||
}
|
||||
// Set connection loss zones
|
||||
for loss in 0..<dataLoss.count {
|
||||
if dataLoss[loss].substring(to: dataLoss[loss].index(dataLoss[loss].startIndex, offsetBy: 5)) == data[point].components(separatedBy: ";")[0].substring(to: data[point].components(separatedBy: ";")[0].index(data[point].components(separatedBy: ";")[0].startIndex, offsetBy: 5)) {
|
||||
|
||||
for loss in lastLossIndex..<dataLoss.count {
|
||||
let time1: String = data[point].components(separatedBy: ";")[0]
|
||||
let hour1: Int = Int(time1.substring(to: time1.index(time1.startIndex, offsetBy: 2)))!
|
||||
let minute1: Int = Int((time1 as NSString).substring(with: NSMakeRange(3, 2)))!
|
||||
let time2: String = dataLoss[loss]
|
||||
let hour2: Int = Int(time2.substring(to: time2.index(time2.startIndex, offsetBy: 2)))!
|
||||
let minute2: Int = Int((time2 as NSString).substring(with: NSMakeRange(3, 2)))!
|
||||
|
||||
if hour1 < hour2 { break }
|
||||
else if hour1 == hour2 && minute1 < minute2 { break }
|
||||
|
||||
if hour1 == hour2 && minute1 == minute2 {
|
||||
let lossPath: NSBezierPath = NSBezierPath()
|
||||
lossPath.move(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(17)))
|
||||
lossPath.line(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(FrequencyGraph.graphSize)))
|
||||
lossPaths.append(lossPath)
|
||||
lastLossIndex = loss
|
||||
}
|
||||
}
|
||||
// Set time scale
|
||||
@ -159,14 +179,14 @@ class FrequencyGraph: NSView {
|
||||
}
|
||||
if (point+offset/2) % 100 == 0 {
|
||||
OperationQueue.main.addOperation {
|
||||
//self.indicator.increment(by: 100)
|
||||
self.indicator.increment(by: 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Put view in display
|
||||
OperationQueue.main.addOperation {
|
||||
|
||||
//self.indicator.isHidden = true
|
||||
self.indicator.isHidden = true
|
||||
self.content.addSubview(self)
|
||||
self.setNeedsDisplay(self.bounds)
|
||||
}
|
||||
|
||||
@ -12,7 +12,16 @@ class GraphWindow: NSWindowController {
|
||||
|
||||
var collectionViewItem: CollectionViewItemMonth!
|
||||
@IBOutlet var scrollView: NSScrollView!
|
||||
let opQueue: OperationQueue = OperationQueue()
|
||||
@IBOutlet var indicator1: NSProgressIndicator!
|
||||
@IBOutlet var indicator2: NSProgressIndicator!
|
||||
@IBOutlet var indicator3: NSProgressIndicator!
|
||||
@IBOutlet var indicator4: NSProgressIndicator!
|
||||
var indicators: [NSProgressIndicator]!
|
||||
|
||||
let loadingQueue1: OperationQueue = OperationQueue()
|
||||
let loadingQueue2: OperationQueue = OperationQueue()
|
||||
let loadingQueue3: OperationQueue = OperationQueue()
|
||||
let loadingQueue4: OperationQueue = OperationQueue()
|
||||
|
||||
override var windowNibName: String! {
|
||||
return "GraphWindow"
|
||||
@ -25,13 +34,18 @@ class GraphWindow: NSWindowController {
|
||||
init(collectionViewItem: CollectionViewItemMonth) {
|
||||
super.init(window: nil)
|
||||
self.collectionViewItem = collectionViewItem
|
||||
opQueue.maxConcurrentOperationCount = 4
|
||||
loadingQueue1.maxConcurrentOperationCount = 1
|
||||
loadingQueue2.maxConcurrentOperationCount = 1
|
||||
loadingQueue3.maxConcurrentOperationCount = 1
|
||||
loadingQueue4.maxConcurrentOperationCount = 1
|
||||
}
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
|
||||
|
||||
indicators = [indicator1, indicator2, indicator3, indicator4]
|
||||
|
||||
var upstreamFiles: [FileWrapper] = []
|
||||
var downstreamFiles: [FileWrapper] = []
|
||||
guard collectionViewItem.dayFW != nil else { return }
|
||||
@ -49,15 +63,40 @@ class GraphWindow: NSWindowController {
|
||||
|
||||
var numGraphs: Int = 0
|
||||
for item in upstreamFiles {
|
||||
let graph: FrequencyGraph = FrequencyGraph(upstream: true, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content)
|
||||
let graph: FrequencyGraph = FrequencyGraph(upstream: true, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content, indicator: indicators[numGraphs%4])
|
||||
graph.dataLoss = collectionViewItem.distribution
|
||||
opQueue.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: false))
|
||||
|
||||
switch numGraphs%4 {
|
||||
case 0:
|
||||
loadingQueue1.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: false))
|
||||
case 1:
|
||||
loadingQueue2.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: false))
|
||||
case 2:
|
||||
loadingQueue3.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: false))
|
||||
case 3:
|
||||
loadingQueue4.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: false))
|
||||
default:
|
||||
NSLog("Mathematics broke today :/")
|
||||
exit(-1)
|
||||
}
|
||||
numGraphs += 1
|
||||
}
|
||||
for item in downstreamFiles {
|
||||
let graph: FrequencyGraph = FrequencyGraph(upstream: false, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content)
|
||||
let graph: FrequencyGraph = FrequencyGraph(upstream: false, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content, indicator: indicators[numGraphs%4])
|
||||
graph.dataLoss = collectionViewItem.distribution
|
||||
opQueue.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: true))
|
||||
switch numGraphs%4 {
|
||||
case 0:
|
||||
loadingQueue1.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: true))
|
||||
case 1:
|
||||
loadingQueue2.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: true))
|
||||
case 2:
|
||||
loadingQueue3.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: true))
|
||||
case 3:
|
||||
loadingQueue4.addOperation(GraphLoadOperation(graph: graph, item: item, downstream: true))
|
||||
default:
|
||||
NSLog("Mathematics broke today :/")
|
||||
exit(-1)
|
||||
}
|
||||
numGraphs += 1
|
||||
}
|
||||
}
|
||||
@ -65,9 +104,27 @@ class GraphWindow: NSWindowController {
|
||||
|
||||
extension GraphWindow: NSWindowDelegate {
|
||||
func windowShouldClose(_ sender: Any) -> Bool {
|
||||
opQueue.cancelAllOperations()
|
||||
collectionViewItem?.isSelected = false
|
||||
collectionViewItem?.view.layer?.borderColor = NSColor.clear.cgColor
|
||||
for op in loadingQueue1.operations {
|
||||
if !op.isFinished {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for op in loadingQueue2.operations {
|
||||
if !op.isFinished {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for op in loadingQueue3.operations {
|
||||
if !op.isFinished {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for op in loadingQueue4.operations {
|
||||
if !op.isFinished {
|
||||
return false
|
||||
}
|
||||
}
|
||||
collectionViewItem.collectionView.deselectAll(self)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,10 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="GraphWindow" customModule="Graphic_Analysis_2" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="indicator1" destination="8yP-S2-Tmf" id="zZl-uV-nPk"/>
|
||||
<outlet property="indicator2" destination="L88-ZK-sVq" id="rbU-2J-gyn"/>
|
||||
<outlet property="indicator3" destination="mwy-Sm-SXX" id="qla-Kp-xnh"/>
|
||||
<outlet property="indicator4" destination="ENn-gG-2is" id="Dq4-mq-fGD"/>
|
||||
<outlet property="scrollView" destination="N7f-tq-7VU" id="e94-84-TFe"/>
|
||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
@ -46,12 +50,28 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="8yP-S2-Tmf">
|
||||
<rect key="frame" x="2" y="497" width="16" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</progressIndicator>
|
||||
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="L88-ZK-sVq">
|
||||
<rect key="frame" x="2" y="473" width="16" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</progressIndicator>
|
||||
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="mwy-Sm-SXX">
|
||||
<rect key="frame" x="2" y="449" width="16" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</progressIndicator>
|
||||
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="ENn-gG-2is">
|
||||
<rect key="frame" x="2" y="425" width="16" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</progressIndicator>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="292" y="185.5"/>
|
||||
<point key="canvasLocation" x="262" y="197"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>461</string>
|
||||
<string>480</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
version 2.1
|
||||
build 461
|
||||
build 480
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user