forked from MacFace/MacFace
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConsumptionForecastInfo.m
More file actions
executable file
·144 lines (118 loc) · 3.53 KB
/
Copy pathConsumptionForecastInfo.m
File metadata and controls
executable file
·144 lines (118 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// ConsumptionForecastInfo.m
// MacFace
//
// Created by rryu on 06/02/19.
// Copyright 2006 rryu. All rights reserved.
// $Id: ConsumptionForecastInfo.m 48 2006-06-03 10:01:58Z rryu $
//
#import "ConsumptionForecastInfo.h"
@implementation ConsumptionForecastInfo
- (id)initWithDiskHistory:(DiskHistory*)diskHistory
{
int i;
FSSize val1,val2,val3;
FSSize range;
int count = [diskHistory count];
// 消費履歴が3件以下の場合は予測ができないので残り日数としてマイナスを返す
if (count < 3) {
consumeRate = 0;
remainDay = -1;
envelopePointCountMax = 0;
envelopePointCount = 0;
envelopePointList = malloc(sizeof(EnvelopePoint) * envelopePointCountMax);
return self;
}
// 上側包絡線を求める --------------------------------------------------------
envelopePointCountMax = count;
envelopePointCount = 0;
envelopePointList = malloc(sizeof(EnvelopePoint) * envelopePointCountMax);
if (envelopePointList == nil) {
[self release];
return nil;
}
// 同じ値として扱うための閾値を求める
int unit = [diskHistory preferredUnit];
int numFractionDigit = [diskHistory preferredFractionDigit];
range = [diskHistory maxFreeSize] - [diskHistory minFreeSize];
FSSize th = (1LL << unit);
for (i = 0; i < numFractionDigit; i++) {
th /= 10;
}
for (; range > th*100; th *= 10);
envelopePointList[envelopePointCount].pos = 0;
envelopePointList[envelopePointCount].size = [diskHistory freeSizeAtIndex:0];
envelopePointCount++;
for (i = 1; i < count-1; i++){
val1 = [diskHistory freeSizeAtIndex:i-1];
val2 = [diskHistory freeSizeAtIndex:i ];
val3 = [diskHistory freeSizeAtIndex:i+1];
if ((val1 - val2 <= th && val2 - val3 > th) || // 右エッジ
(val3 - val2 <= th && val2 - val1 > th)) { // 左エッジ
envelopePointList[envelopePointCount].pos = i;
envelopePointList[envelopePointCount].size = val2;
envelopePointCount++;
}
}
envelopePointList[envelopePointCount].pos = i;
envelopePointList[envelopePointCount].size = [diskHistory freeSizeAtIndex:i];
envelopePointCount++;
// 消費予測を行う -----------------------------------------------------------
double sx = 0.0;
double sy = 0.0;
double sxy = 0.0;
double sxx = 0.0;
int start_pos;
int end_pos;
int p_count = 0;
int pos;
// 消費率を求める
for (i = envelopePointCount-2; i >= 0; i--) {
start_pos = envelopePointList[i].pos+1;
end_pos = envelopePointList[i+1].pos;
p_count += end_pos - start_pos + 1;
// 最小二乗法で消費率を求める
for (pos = start_pos; pos <= end_pos; pos++) {
val1 = [diskHistory freeSizeAtIndex:pos];
sx += pos;
sy += val1;
sxy += (double)pos * val1;
sxx += pos * pos;
}
consumeRate = -(p_count*sxy - sx*sy) / (p_count*sxx - sx*sx);
if (p_count >= 5 && consumeRate > 0.0) break;
}
// 残り日数を求める
if (consumeRate > 0) {
remainDay = [diskHistory currentFreeSize] / consumeRate;
} else {
remainDay = -1; // 消費率がマイナスの場合は仮にー1としておく
}
return self;
}
- (void)dealloc
{
free(envelopePointList);
[super dealloc];
}
+ (id)consumptionForecastInfoWithDiskHistory:(DiskHistory*)diskHistory
{
return [[[ConsumptionForecastInfo alloc] initWithDiskHistory:diskHistory] autorelease];
}
- (double)consumeRate
{
return consumeRate;
}
- (double)remainDay
{
return remainDay;
}
- (int)envelopePointCount
{
return envelopePointCount;
}
- (EnvelopePoint)envelopePointAt:(int)index
{
return envelopePointList[index];
}
@end