{storagenode,web/multinode}: fix storage usage db/cache retrieval queries

The query changes we did while fixing the usage graph led to wrong
payout calculations directly linked to disk space.

This change:

- avoids converting from Bh to B directly in the query
- returns the at_rest_total in the original bytes*hour value
- returns at_rest_total_bytes as the calculated disk spaced used in bytes
- uses the at_rest_total_bytes only for the disk space graph
- return summary_bytes as the average disk space used within the specified date
- updates the disk space graph header to "average disk space used this month"

The total disk used in the month is also displayed in B not B*day

Resolves https://github.com/storj/storj/issues/5355

Change-Id: I2cfefb0fe711f9c59de2adb547c4ab50b05c7cbb
This commit is contained in:
Clement Sam 2022-12-05 14:10:04 +00:00
parent 3cf7ebfad0
commit 7461ffe148
24 changed files with 397 additions and 358 deletions

View File

@ -288,7 +288,7 @@ func (m *StorageUsageRequest) GetTo() time.Time {
type StorageUsageResponse struct { type StorageUsageResponse struct {
StorageUsage []*StorageUsage `protobuf:"bytes,1,rep,name=storage_usage,json=storageUsage,proto3" json:"storage_usage,omitempty"` StorageUsage []*StorageUsage `protobuf:"bytes,1,rep,name=storage_usage,json=storageUsage,proto3" json:"storage_usage,omitempty"`
Summary float64 `protobuf:"fixed64,2,opt,name=summary,proto3" json:"summary,omitempty"` Summary float64 `protobuf:"fixed64,2,opt,name=summary,proto3" json:"summary,omitempty"`
SummaryBytes float64 `protobuf:"fixed64,3,opt,name=summary_bytes,json=summaryBytes,proto3" json:"summary_bytes,omitempty"` AverageUsageBytes float64 `protobuf:"fixed64,3,opt,name=average_usage_bytes,json=averageUsageBytes,proto3" json:"average_usage_bytes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -332,9 +332,9 @@ func (m *StorageUsageResponse) GetSummary() float64 {
return 0 return 0
} }
func (m *StorageUsageResponse) GetSummaryBytes() float64 { func (m *StorageUsageResponse) GetAverageUsageBytes() float64 {
if m != nil { if m != nil {
return m.SummaryBytes return m.AverageUsageBytes
} }
return 0 return 0
} }
@ -397,7 +397,7 @@ func (m *StorageUsageSatelliteRequest) GetTo() time.Time {
type StorageUsageSatelliteResponse struct { type StorageUsageSatelliteResponse struct {
StorageUsage []*StorageUsage `protobuf:"bytes,1,rep,name=storage_usage,json=storageUsage,proto3" json:"storage_usage,omitempty"` StorageUsage []*StorageUsage `protobuf:"bytes,1,rep,name=storage_usage,json=storageUsage,proto3" json:"storage_usage,omitempty"`
Summary float64 `protobuf:"fixed64,2,opt,name=summary,proto3" json:"summary,omitempty"` Summary float64 `protobuf:"fixed64,2,opt,name=summary,proto3" json:"summary,omitempty"`
SummaryBytes float64 `protobuf:"fixed64,3,opt,name=summary_bytes,json=summaryBytes,proto3" json:"summary_bytes,omitempty"` AverageUsageBytes float64 `protobuf:"fixed64,3,opt,name=average_usage_bytes,json=averageUsageBytes,proto3" json:"average_usage_bytes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -441,9 +441,9 @@ func (m *StorageUsageSatelliteResponse) GetSummary() float64 {
return 0 return 0
} }
func (m *StorageUsageSatelliteResponse) GetSummaryBytes() float64 { func (m *StorageUsageSatelliteResponse) GetAverageUsageBytes() float64 {
if m != nil { if m != nil {
return m.SummaryBytes return m.AverageUsageBytes
} }
return 0 return 0
} }
@ -4213,185 +4213,186 @@ func init() {
func init() { proto.RegisterFile("multinode.proto", fileDescriptor_9a45fd79b06f3a1b) } func init() { proto.RegisterFile("multinode.proto", fileDescriptor_9a45fd79b06f3a1b) }
var fileDescriptor_9a45fd79b06f3a1b = []byte{ var fileDescriptor_9a45fd79b06f3a1b = []byte{
// 2878 bytes of a gzipped FileDescriptorProto // 2886 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcd, 0x6f, 0xdc, 0xc6, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcb, 0x6f, 0x1c, 0xc7,
0x15, 0x2f, 0xf5, 0xb1, 0xab, 0x7d, 0xbb, 0xfa, 0x9a, 0xe8, 0x63, 0x45, 0xcb, 0x92, 0x4c, 0xb9, 0xd1, 0xff, 0x86, 0x8f, 0x5d, 0x6e, 0xed, 0xf2, 0xd5, 0xe2, 0x63, 0x39, 0xe2, 0x4b, 0x43, 0x7d,
0xb6, 0xdc, 0xd8, 0x72, 0xa2, 0x04, 0x69, 0x93, 0x26, 0x68, 0x56, 0xb6, 0x13, 0x29, 0xb1, 0x63, 0x12, 0x15, 0x4b, 0x94, 0x4d, 0x1b, 0x4e, 0xec, 0xd8, 0x88, 0x97, 0x92, 0x6c, 0xd2, 0x96, 0x2c,
0x95, 0xb2, 0xd3, 0x20, 0x2e, 0xc2, 0x50, 0xcb, 0x91, 0xc4, 0x98, 0x4b, 0x6e, 0xc8, 0x59, 0xb9, 0x66, 0x28, 0x39, 0x86, 0x15, 0x78, 0x3d, 0xe4, 0x34, 0xc9, 0xb1, 0x67, 0x67, 0xd6, 0x33, 0xbd,
0x02, 0x8a, 0xa0, 0x87, 0x36, 0x3d, 0x15, 0x28, 0xd0, 0x5b, 0xd0, 0xbf, 0xa1, 0x87, 0x5e, 0x7a, 0x64, 0x08, 0x04, 0x46, 0x0e, 0x89, 0x73, 0x0a, 0x90, 0xb3, 0x11, 0xe4, 0x9a, 0x5b, 0x0e, 0xb9,
0xec, 0xad, 0x08, 0xd0, 0xff, 0xa0, 0x87, 0x14, 0xe8, 0xad, 0x97, 0x5e, 0x7a, 0xeb, 0xa9, 0x98, 0xe4, 0x98, 0x5b, 0x60, 0x20, 0xff, 0x41, 0x0e, 0x0e, 0x90, 0x5b, 0x2e, 0xb9, 0xe4, 0x96, 0x53,
0x0f, 0x72, 0x39, 0xfc, 0x5a, 0x89, 0xeb, 0x40, 0xb9, 0x71, 0xde, 0xbc, 0xf7, 0x9b, 0xf7, 0xde, 0xd0, 0x8f, 0x79, 0xf4, 0xbc, 0x96, 0x9c, 0x95, 0x41, 0xdf, 0xa6, 0xab, 0xab, 0x7e, 0x5d, 0x55,
0xcc, 0x3c, 0xce, 0x7b, 0x33, 0x30, 0xdd, 0xe9, 0x39, 0xc4, 0x76, 0x3d, 0x0b, 0x6f, 0x76, 0x7d, 0xdd, 0x5d, 0xd3, 0x55, 0xdd, 0x30, 0xd9, 0xe9, 0xd9, 0xc4, 0x72, 0x5c, 0x13, 0x6f, 0x74, 0x3d,
0x8f, 0x78, 0xa8, 0x16, 0x11, 0x54, 0x38, 0xf2, 0x8e, 0x3c, 0x4e, 0x56, 0x57, 0x8f, 0x3c, 0xef, 0x97, 0xb8, 0xa8, 0x16, 0x12, 0x54, 0x38, 0x72, 0x8f, 0x5c, 0x4e, 0x56, 0x57, 0x8e, 0x5c, 0xf7,
0xc8, 0xc1, 0xb7, 0x59, 0xeb, 0xa0, 0x77, 0x78, 0x9b, 0xd8, 0x1d, 0x1c, 0x10, 0xb3, 0xd3, 0xe5, 0xc8, 0xc6, 0x77, 0x59, 0x6b, 0xbf, 0x77, 0x78, 0x97, 0x58, 0x1d, 0xec, 0x13, 0xa3, 0xd3, 0xe5,
0x0c, 0xda, 0x06, 0x4c, 0xea, 0xf8, 0xf3, 0x1e, 0x0e, 0xc8, 0x0e, 0x36, 0x2d, 0xec, 0xa3, 0x45, 0x0c, 0xda, 0x3a, 0x8c, 0xeb, 0xf8, 0xf3, 0x1e, 0xf6, 0xc9, 0x36, 0x36, 0x4c, 0xec, 0xa1, 0x79,
0xa8, 0x9a, 0x5d, 0xdb, 0x78, 0x8a, 0x4f, 0x9b, 0xca, 0x9a, 0xb2, 0xd1, 0xd0, 0x2b, 0x66, 0xd7, 0xa8, 0x1a, 0x5d, 0xab, 0xfd, 0x19, 0x3e, 0x6b, 0x2a, 0xab, 0xca, 0x7a, 0x43, 0xaf, 0x18, 0x5d,
0x7e, 0x1f, 0x9f, 0x6a, 0x77, 0x61, 0xe6, 0xae, 0x1d, 0x3c, 0xdd, 0xef, 0x9a, 0x6d, 0x2c, 0x44, 0xeb, 0x3d, 0x7c, 0xa6, 0xdd, 0x87, 0xa9, 0xfb, 0x96, 0xff, 0xd9, 0x5e, 0xd7, 0x38, 0xc0, 0x42,
0xd0, 0x4b, 0x50, 0x39, 0x66, 0x62, 0x8c, 0xb7, 0xbe, 0xd5, 0xdc, 0xec, 0xeb, 0x25, 0xc1, 0xea, 0x04, 0xbd, 0x08, 0x95, 0x63, 0x26, 0xc6, 0x78, 0xeb, 0x9b, 0xcd, 0x8d, 0x48, 0x2f, 0x09, 0x56,
0x82, 0x4f, 0xfb, 0xab, 0x02, 0xb3, 0x31, 0x98, 0xa0, 0xeb, 0xb9, 0x01, 0x46, 0xcb, 0x50, 0x33, 0x17, 0x7c, 0xda, 0x5f, 0x14, 0x98, 0x8e, 0xc1, 0xf8, 0x5d, 0xd7, 0xf1, 0x31, 0x5a, 0x84, 0x9a,
0x1d, 0xc7, 0x6b, 0x9b, 0x04, 0x5b, 0x0c, 0x6a, 0x54, 0xef, 0x13, 0xd0, 0x2a, 0xd4, 0x7b, 0x01, 0x61, 0xdb, 0xee, 0x81, 0x41, 0xb0, 0xc9, 0xa0, 0x86, 0xf5, 0x88, 0x80, 0x56, 0xa0, 0xde, 0xf3,
0xb6, 0x8c, 0xae, 0x8d, 0xdb, 0x38, 0x68, 0x8e, 0xb0, 0x7e, 0xa0, 0xa4, 0x3d, 0x46, 0x41, 0x97, 0xb1, 0xd9, 0xee, 0x5a, 0xf8, 0x00, 0xfb, 0xcd, 0x21, 0xd6, 0x0f, 0x94, 0xb4, 0xcb, 0x28, 0x68,
0x81, 0xb5, 0x0c, 0xe2, 0x9b, 0xc1, 0x71, 0x73, 0x94, 0xcb, 0x53, 0xca, 0x23, 0x4a, 0x40, 0x08, 0x09, 0x58, 0xab, 0x4d, 0x3c, 0xc3, 0x3f, 0x6e, 0x0e, 0x73, 0x79, 0x4a, 0x79, 0x42, 0x09, 0x08,
0xc6, 0x0e, 0x7d, 0x8c, 0x9b, 0x63, 0xac, 0x83, 0x7d, 0xb3, 0x11, 0x4f, 0x4c, 0xdb, 0x31, 0x0f, 0xc1, 0xc8, 0xa1, 0x87, 0x71, 0x73, 0x84, 0x75, 0xb0, 0x6f, 0x36, 0xe2, 0x89, 0x61, 0xd9, 0xc6,
0x1c, 0xdc, 0x1c, 0x17, 0x23, 0x86, 0x04, 0xa4, 0xc2, 0x84, 0x77, 0x82, 0x7d, 0x0a, 0xd1, 0xac, 0xbe, 0x8d, 0x9b, 0xa3, 0x62, 0xc4, 0x80, 0x80, 0x54, 0x18, 0x73, 0x4f, 0xb0, 0x47, 0x21, 0x9a,
0xb0, 0xce, 0xa8, 0xad, 0xfd, 0x49, 0x81, 0xc6, 0x3e, 0xf1, 0x7c, 0xf3, 0x08, 0x3f, 0x0e, 0xcc, 0x15, 0xd6, 0x19, 0xb6, 0xb5, 0x3f, 0x2a, 0xd0, 0xd8, 0x23, 0xae, 0x67, 0x1c, 0xe1, 0xa7, 0xbe,
0x23, 0x8c, 0x34, 0x98, 0x34, 0x89, 0xe1, 0xe3, 0x80, 0x18, 0xc4, 0x23, 0xa6, 0xc3, 0x0c, 0x50, 0x71, 0x84, 0x91, 0x06, 0xe3, 0x06, 0x69, 0x7b, 0xd8, 0x27, 0x6d, 0xe2, 0x12, 0xc3, 0x66, 0x06,
0xf4, 0xba, 0x49, 0x74, 0x1c, 0x90, 0x47, 0x94, 0x84, 0xde, 0x87, 0x29, 0xdb, 0x25, 0xd8, 0x3f, 0x28, 0x7a, 0xdd, 0x20, 0x3a, 0xf6, 0xc9, 0x13, 0x4a, 0x42, 0xef, 0xc1, 0x84, 0xe5, 0x10, 0xec,
0x31, 0x1d, 0x23, 0x20, 0xa6, 0x4f, 0x98, 0x15, 0xf5, 0x2d, 0x75, 0x93, 0x4f, 0xd0, 0x66, 0x38, 0x9d, 0x18, 0x76, 0xdb, 0x27, 0x86, 0x47, 0x98, 0x15, 0xf5, 0x4d, 0x75, 0x83, 0x4f, 0xd0, 0x46,
0x41, 0x9b, 0x8f, 0xc2, 0x09, 0xda, 0x9e, 0xf8, 0xfa, 0x9b, 0xd5, 0xef, 0xfd, 0xfe, 0x9f, 0xab, 0x30, 0x41, 0x1b, 0x4f, 0x82, 0x09, 0xda, 0x1a, 0xfb, 0xfa, 0x9b, 0x95, 0xff, 0xfb, 0xed, 0x3f,
0x8a, 0x3e, 0x19, 0xca, 0xee, 0x53, 0x51, 0x74, 0x0b, 0x5e, 0x90, 0x06, 0x34, 0x0e, 0x4e, 0x09, 0x56, 0x14, 0x7d, 0x3c, 0x90, 0xdd, 0xa3, 0xa2, 0xe8, 0x0e, 0x5c, 0x91, 0x06, 0x6c, 0xef, 0x9f,
0x0e, 0x98, 0xdd, 0x8a, 0x3e, 0x13, 0x1b, 0x76, 0x9b, 0xd2, 0xb5, 0xbf, 0x28, 0xf0, 0x42, 0x5c, 0x11, 0xec, 0x33, 0xbb, 0x15, 0x7d, 0x2a, 0x36, 0xec, 0x16, 0xa5, 0x6b, 0x7f, 0x56, 0xe0, 0x4a,
0xe1, 0xd2, 0x93, 0x87, 0x7e, 0x44, 0x1d, 0xe9, 0x75, 0xce, 0xa5, 0x3b, 0x93, 0x40, 0xaf, 0xc2, 0x5c, 0xe1, 0xd2, 0x93, 0x87, 0x7e, 0x40, 0x1d, 0xe9, 0x76, 0x2e, 0xa4, 0x3b, 0x93, 0x40, 0xaf,
0x08, 0xf1, 0x98, 0x86, 0x67, 0x95, 0x1b, 0x21, 0x9e, 0xf6, 0x07, 0x05, 0xe6, 0x64, 0xcd, 0xc5, 0xc0, 0x10, 0x71, 0x99, 0x86, 0xe7, 0x95, 0x1b, 0x22, 0xae, 0xf6, 0x7b, 0x05, 0x66, 0x64, 0xcd,
0x7a, 0x79, 0x13, 0x26, 0x03, 0x4e, 0x37, 0x7a, 0xb4, 0xa3, 0xa9, 0xac, 0x8d, 0x6e, 0xd4, 0xb7, 0xc5, 0x7a, 0x79, 0x03, 0xc6, 0x7d, 0x4e, 0x6f, 0xf7, 0x68, 0x47, 0x53, 0x59, 0x1d, 0x5e, 0xaf,
0x16, 0x63, 0x16, 0x48, 0x72, 0x8d, 0x20, 0x3e, 0x61, 0x4d, 0xa8, 0x06, 0xbd, 0x4e, 0xc7, 0xf4, 0x6f, 0xce, 0xc7, 0x2c, 0x90, 0xe4, 0x1a, 0x7e, 0x7c, 0xc2, 0x9a, 0x50, 0xf5, 0x7b, 0x9d, 0x8e,
0x4f, 0x99, 0x25, 0x8a, 0x1e, 0x36, 0xd1, 0x3a, 0x4c, 0x8a, 0x4f, 0xc9, 0xa7, 0x0d, 0x41, 0xe4, 0xe1, 0x9d, 0x31, 0x4b, 0x14, 0x3d, 0x68, 0xa2, 0x0d, 0xb8, 0x62, 0x9c, 0xe0, 0x08, 0x57, 0xf2,
0xfe, 0xfc, 0xaf, 0x02, 0xcb, 0x71, 0xf4, 0x7d, 0x93, 0x60, 0xc7, 0xb1, 0xc9, 0x10, 0x8e, 0x7d, 0xec, 0xb4, 0xe8, 0x62, 0x20, 0xdc, 0xb5, 0xff, 0x51, 0x60, 0x31, 0x3e, 0xd0, 0x9e, 0x41, 0xb0,
0x19, 0x1a, 0x41, 0x88, 0x62, 0xd8, 0x16, 0x53, 0xab, 0xb1, 0x3d, 0x45, 0x9d, 0xf1, 0x8f, 0x6f, 0x6d, 0x5b, 0x64, 0x00, 0x1f, 0xbf, 0x04, 0x0d, 0x3f, 0x40, 0x69, 0x5b, 0x26, 0xd3, 0xb0, 0xb1,
0x56, 0x2b, 0x1f, 0x78, 0x16, 0xde, 0xbd, 0xab, 0xd7, 0x23, 0x9e, 0x5d, 0x2b, 0x9a, 0x8b, 0xd1, 0x35, 0x41, 0xfd, 0xf2, 0xf7, 0x6f, 0x56, 0x2a, 0xef, 0xbb, 0x26, 0xde, 0xb9, 0xaf, 0xd7, 0x43,
0x92, 0x73, 0x31, 0x76, 0xce, 0xb9, 0xf8, 0xa3, 0x02, 0x97, 0x73, 0xac, 0xfe, 0x2e, 0x4c, 0xca, 0x9e, 0x1d, 0x33, 0x9c, 0x96, 0xe1, 0x92, 0xd3, 0x32, 0x72, 0xc1, 0x69, 0xf9, 0x83, 0x02, 0x4b,
0x1e, 0x2c, 0x6f, 0x9b, 0xae, 0xf5, 0xcc, 0xb6, 0xc8, 0xf1, 0x03, 0xcf, 0x25, 0xc7, 0xfb, 0xbc, 0x39, 0x56, 0x7f, 0xc7, 0xe6, 0x67, 0x17, 0x16, 0xb7, 0x0c, 0xc7, 0x3c, 0xb5, 0x4c, 0x72, 0xfc,
0xb7, 0x7c, 0xa4, 0x7a, 0x05, 0x2e, 0xe7, 0x20, 0x0a, 0x7b, 0x11, 0x8c, 0xb1, 0x00, 0xc1, 0xe3, 0xc8, 0x75, 0xc8, 0xf1, 0x1e, 0x07, 0x2a, 0x1f, 0xbf, 0x5e, 0x86, 0xa5, 0x1c, 0x44, 0x61, 0x3a,
0x15, 0xfb, 0xd6, 0x7e, 0xab, 0xc0, 0x5a, 0x24, 0x25, 0x04, 0x2e, 0x64, 0x7d, 0x68, 0x6f, 0xc1, 0x82, 0x11, 0x16, 0x36, 0x78, 0x14, 0x63, 0xdf, 0xda, 0xaf, 0x15, 0x58, 0x0d, 0xa5, 0x84, 0xc0,
0x95, 0x02, 0x45, 0x84, 0x09, 0x31, 0xa7, 0x73, 0x2b, 0xc2, 0xa6, 0xf6, 0x3e, 0x2c, 0x26, 0xc5, 0xa5, 0x2c, 0x15, 0xed, 0x4d, 0xb8, 0x56, 0xa0, 0x88, 0x30, 0x21, 0xe6, 0x7f, 0x6e, 0x45, 0xd0,
0xcb, 0xbb, 0xf2, 0x55, 0x68, 0xa6, 0xc1, 0x06, 0xaa, 0xf0, 0x6b, 0x05, 0x2e, 0xdf, 0x3b, 0xf2, 0xd4, 0xde, 0x83, 0xf9, 0xa4, 0x78, 0x79, 0x57, 0xbe, 0x02, 0xcd, 0x34, 0x58, 0x5f, 0x15, 0x7e,
0x71, 0x10, 0x5c, 0xa8, 0x23, 0xdf, 0x80, 0x95, 0x3c, 0x2d, 0x06, 0x9a, 0xb0, 0x03, 0x73, 0x92, 0xa9, 0xc0, 0xd2, 0x83, 0x23, 0x0f, 0xfb, 0xfe, 0xa5, 0x3a, 0xf2, 0x75, 0x58, 0xce, 0xd3, 0xa2,
0x6c, 0x79, 0x17, 0xbe, 0x0c, 0xf3, 0x09, 0xa4, 0x81, 0x83, 0xff, 0x46, 0x81, 0x95, 0x5d, 0xf7, 0xaf, 0x09, 0xdb, 0x30, 0x23, 0xc9, 0x96, 0x77, 0xe1, 0x4b, 0x30, 0x9b, 0x40, 0xea, 0x3b, 0xf8,
0xe2, 0x1d, 0xf8, 0x63, 0x58, 0xcd, 0x55, 0x63, 0xa0, 0x11, 0xbb, 0x30, 0x2f, 0x0b, 0x97, 0x77, 0xaf, 0x14, 0x58, 0xde, 0x71, 0x2e, 0xdf, 0x81, 0x3f, 0x84, 0x95, 0x5c, 0x35, 0xfa, 0x1a, 0xb1,
0xe1, 0x16, 0x2c, 0x24, 0xa1, 0x06, 0x0e, 0xff, 0x4b, 0x98, 0xbf, 0x6b, 0xda, 0xce, 0x05, 0x79, 0x03, 0xb3, 0xb2, 0x70, 0x79, 0x17, 0x6e, 0xc2, 0x5c, 0x12, 0xaa, 0xef, 0xf0, 0x3f, 0x87, 0xd9,
0x6e, 0x1f, 0x16, 0x92, 0xa3, 0x0b, 0x8d, 0x5f, 0x87, 0x06, 0x8b, 0xb1, 0x86, 0xef, 0x39, 0x4e, 0xfb, 0x86, 0x65, 0x5f, 0x92, 0xe7, 0xf6, 0x60, 0x2e, 0x39, 0xba, 0xd0, 0xf8, 0x35, 0x68, 0xf0,
0xaf, 0x2b, 0x42, 0xed, 0x42, 0x4c, 0x09, 0x1e, 0x63, 0x59, 0xaf, 0x5e, 0xef, 0xf5, 0x1b, 0xda, 0xb0, 0xe8, 0xb9, 0xb6, 0xdd, 0xeb, 0x8a, 0xa8, 0x3b, 0x17, 0x53, 0x82, 0x87, 0x5b, 0xd6, 0xab,
0xdb, 0xd0, 0x60, 0xa0, 0xe5, 0x1d, 0xf9, 0x1e, 0x4c, 0x0a, 0x84, 0xe1, 0xb5, 0xf9, 0xbb, 0x02, 0xd7, 0x7b, 0x51, 0x43, 0x7b, 0x0b, 0x1a, 0x0c, 0xb4, 0xbc, 0x23, 0xdf, 0x85, 0x71, 0x81, 0x30,
0xf5, 0x58, 0x27, 0xba, 0x01, 0x15, 0xcc, 0xe6, 0x48, 0x68, 0x33, 0x1b, 0x03, 0xe1, 0x1b, 0x40, 0xb8, 0x36, 0x7f, 0x53, 0xa0, 0x1e, 0xeb, 0x44, 0xb7, 0xa0, 0x82, 0xd9, 0x1c, 0x09, 0x6d, 0xa6,
0x17, 0x0c, 0xe8, 0x26, 0x54, 0x6d, 0x3e, 0x9f, 0xe2, 0x40, 0x82, 0x62, 0xbc, 0x62, 0xa6, 0xf5, 0x63, 0x20, 0x7c, 0x03, 0xe8, 0x82, 0x01, 0xdd, 0x86, 0xaa, 0xc5, 0xe7, 0x53, 0x1c, 0x53, 0x50,
0x90, 0x05, 0x2d, 0x40, 0xc5, 0xc2, 0x0e, 0x26, 0x58, 0x9c, 0x0f, 0x45, 0x2b, 0xe3, 0x64, 0x36, 0x8c, 0x57, 0xcc, 0xb4, 0x1e, 0xb0, 0xa0, 0x39, 0xa8, 0x98, 0xd8, 0xc6, 0x04, 0x8b, 0x53, 0xa3,
0x56, 0xfa, 0x64, 0xa6, 0xdd, 0x87, 0xca, 0xbd, 0x68, 0x38, 0x1f, 0x77, 0x4d, 0xdb, 0x17, 0x2b, 0x68, 0x65, 0x9c, 0xd7, 0x46, 0x4a, 0x9f, 0xd7, 0xb4, 0x87, 0x50, 0x79, 0x10, 0x0e, 0xe7, 0xe1,
0x4a, 0xb4, 0xd0, 0x1c, 0x8c, 0x9b, 0x3d, 0xcb, 0x26, 0xe2, 0x14, 0xcb, 0x1b, 0x94, 0xca, 0x7f, 0xae, 0x61, 0x79, 0x62, 0x45, 0x89, 0x16, 0x9a, 0x81, 0x51, 0xa3, 0x67, 0x5a, 0x44, 0x9c, 0x6d,
0x99, 0x5c, 0x37, 0xde, 0xd0, 0x7e, 0x08, 0xd5, 0x5d, 0x57, 0x86, 0xb3, 0x24, 0x38, 0xab, 0x2f, 0x79, 0x83, 0x52, 0xf9, 0xdf, 0x93, 0xeb, 0xc6, 0x1b, 0xda, 0xf7, 0xa1, 0xba, 0xe3, 0xc8, 0x70,
0x38, 0x12, 0x17, 0xdc, 0x86, 0xa9, 0x0f, 0xb1, 0x1f, 0xd8, 0x9e, 0x5b, 0x7e, 0x92, 0x5f, 0x84, 0xa6, 0x04, 0x67, 0x46, 0x82, 0x43, 0x71, 0xc1, 0x2d, 0x98, 0xf8, 0x00, 0x7b, 0xbe, 0xe5, 0x3a,
0xe9, 0x08, 0xa3, 0xbf, 0x4d, 0x4e, 0x38, 0x89, 0xa1, 0xd4, 0xf4, 0xb0, 0xa9, 0xbd, 0x03, 0xe8, 0xe5, 0x27, 0xf9, 0x05, 0x98, 0x0c, 0x31, 0xa2, 0x6d, 0x72, 0xc2, 0x49, 0x0c, 0xa5, 0xa6, 0x07,
0xbe, 0x19, 0x90, 0x3b, 0x9e, 0x4b, 0xcc, 0x36, 0x29, 0x3f, 0xe8, 0x27, 0xf0, 0x82, 0x84, 0x23, 0x4d, 0xed, 0x6d, 0x40, 0x0f, 0x0d, 0x9f, 0xdc, 0x73, 0x1d, 0x62, 0x1c, 0x90, 0xf2, 0x83, 0x7e,
0x06, 0x7e, 0x17, 0x1a, 0x8e, 0x19, 0x10, 0xa3, 0xcd, 0xe9, 0x02, 0xee, 0x6c, 0x33, 0x54, 0x77, 0x0c, 0x57, 0x24, 0x1c, 0x31, 0xf0, 0x3b, 0xd0, 0xb0, 0x0d, 0x9f, 0xb4, 0x0f, 0x38, 0x5d, 0xc0,
0xfa, 0x80, 0xda, 0x2f, 0x60, 0x56, 0xc7, 0xdd, 0x1e, 0x31, 0xc9, 0x30, 0xbe, 0x29, 0xb3, 0x95, 0x9d, 0x6f, 0x86, 0xea, 0x76, 0x04, 0xa8, 0xfd, 0x0c, 0xa6, 0x75, 0xdc, 0xed, 0x11, 0x83, 0x0c,
0xbf, 0x52, 0xa0, 0xde, 0xa2, 0x73, 0xfd, 0x33, 0xdb, 0xb5, 0xbc, 0x67, 0xd4, 0xa4, 0x67, 0xec, 0xe2, 0x9b, 0x32, 0x5b, 0xf9, 0x2b, 0x05, 0xea, 0x2d, 0x3a, 0xd7, 0x3f, 0xb1, 0x1c, 0xd3, 0x3d,
0x4b, 0x2c, 0xba, 0x73, 0x99, 0xc4, 0x25, 0x79, 0x32, 0x70, 0x05, 0x1a, 0x9e, 0xeb, 0xd8, 0x2e, 0xa5, 0x26, 0x9d, 0xb2, 0x2f, 0xb1, 0xe8, 0x2e, 0x64, 0x12, 0x97, 0xe4, 0x29, 0xc2, 0x35, 0x68,
0x36, 0xda, 0x5e, 0xcf, 0xe5, 0xeb, 0x6a, 0x5c, 0xaf, 0x73, 0xda, 0x1d, 0x4a, 0xa2, 0xf9, 0x13, 0xb8, 0x8e, 0x6d, 0x39, 0xb8, 0x7d, 0xe0, 0xf6, 0x1c, 0xbe, 0xae, 0x46, 0xf5, 0x3a, 0xa7, 0xdd,
0xcf, 0x13, 0x38, 0xc7, 0x28, 0xe3, 0x00, 0x46, 0x62, 0x0c, 0xda, 0xff, 0xaa, 0x80, 0xe2, 0x7e, 0xa3, 0x24, 0x9a, 0x55, 0xf1, 0xec, 0x81, 0x73, 0x0c, 0x33, 0x0e, 0x60, 0x24, 0xc6, 0xa0, 0xfd,
0x89, 0x0e, 0x74, 0x15, 0x0e, 0x23, 0xb4, 0xbb, 0x2a, 0x39, 0x26, 0xc9, 0xbe, 0xf9, 0x90, 0xf1, 0xb7, 0x0a, 0x28, 0xee, 0x97, 0xf0, 0x6c, 0x57, 0xe1, 0x30, 0x42, 0xbb, 0xeb, 0x92, 0x63, 0x92,
0xea, 0x42, 0x06, 0xbd, 0x1e, 0x5f, 0xe9, 0xf5, 0xad, 0xf5, 0x62, 0x61, 0xe6, 0x9b, 0x70, 0x3b, 0xec, 0x1b, 0x8f, 0x19, 0xaf, 0x2e, 0x64, 0xd0, 0x6b, 0xf1, 0x95, 0x5e, 0xdf, 0x5c, 0x2b, 0x16,
0x3c, 0x80, 0x69, 0xcb, 0x0e, 0x3e, 0xef, 0x99, 0x8e, 0x7d, 0x68, 0x63, 0xcb, 0x30, 0xc9, 0x19, 0x66, 0xbe, 0x09, 0xb6, 0xc3, 0x23, 0x98, 0x34, 0x2d, 0xff, 0xf3, 0x9e, 0x61, 0x5b, 0x87, 0x16,
0x8f, 0xb9, 0x0a, 0xf3, 0xcf, 0x54, 0x5c, 0xb8, 0x45, 0xa8, 0xaf, 0x83, 0x5e, 0xd0, 0xc5, 0xae, 0x36, 0xdb, 0x06, 0x39, 0xe7, 0x89, 0x57, 0x61, 0xfe, 0x99, 0x88, 0x0b, 0xb7, 0x08, 0xf5, 0xb5,
0xc5, 0xb1, 0xc6, 0xce, 0x81, 0x55, 0x8f, 0x24, 0x5b, 0x04, 0x7d, 0x08, 0x73, 0xde, 0xe1, 0x21, 0xdf, 0xf3, 0xbb, 0xd8, 0x31, 0x39, 0xd6, 0xc8, 0x05, 0xb0, 0xea, 0xa1, 0x64, 0x8b, 0xa0, 0x0f,
0x73, 0xb6, 0x04, 0x38, 0x7e, 0x0e, 0x40, 0x24, 0x10, 0xf6, 0x63, 0xb8, 0x4f, 0x60, 0x31, 0xc4, 0x60, 0xc6, 0x3d, 0x3c, 0x64, 0xce, 0x96, 0x00, 0x47, 0x2f, 0x00, 0x88, 0x04, 0xc2, 0x5e, 0x0c,
0xed, 0xb9, 0x16, 0xf6, 0x0d, 0x1f, 0x9f, 0xd8, 0xf8, 0x19, 0x85, 0xae, 0x9c, 0x03, 0x3a, 0x54, 0xf7, 0x19, 0xcc, 0x07, 0xb8, 0x3d, 0xc7, 0xc4, 0x5e, 0xdb, 0xc3, 0x27, 0x16, 0x3e, 0xa5, 0xd0,
0xee, 0x31, 0xc5, 0xd0, 0x19, 0x44, 0x8b, 0xa0, 0x16, 0xd4, 0x4e, 0x30, 0x21, 0x5c, 0xd3, 0xda, 0x95, 0x0b, 0x40, 0x07, 0xca, 0x3d, 0xa5, 0x18, 0x3a, 0x83, 0x68, 0x11, 0xd4, 0x82, 0xda, 0x09,
0x39, 0xe0, 0x26, 0xb8, 0x58, 0x8b, 0xa0, 0x3b, 0x00, 0xbd, 0xae, 0x65, 0x0a, 0x8c, 0xea, 0x39, 0x26, 0x84, 0x6b, 0x5a, 0xbb, 0x00, 0xdc, 0x18, 0x17, 0x6b, 0x11, 0x74, 0x0f, 0xa0, 0xd7, 0x35,
0x96, 0x6a, 0x4d, 0xc8, 0x71, 0x3d, 0x3e, 0xf3, 0x6c, 0x97, 0x63, 0x4c, 0x9c, 0x03, 0x63, 0x82, 0x0d, 0x81, 0x51, 0xbd, 0xc0, 0x52, 0xad, 0x09, 0x39, 0xae, 0xc7, 0xa7, 0xae, 0xe5, 0x70, 0x8c,
0x8b, 0xb5, 0x88, 0xba, 0x02, 0x15, 0xbe, 0xc8, 0x68, 0xdc, 0x0b, 0xda, 0x9e, 0x8f, 0x45, 0xae, 0xb1, 0x0b, 0x60, 0x8c, 0x71, 0xb1, 0x16, 0x51, 0x97, 0xa1, 0xc2, 0x17, 0x19, 0x8d, 0x7b, 0xfe,
0xcd, 0x1b, 0xea, 0x9f, 0x47, 0x60, 0xbc, 0x15, 0x06, 0xd4, 0x74, 0x3f, 0xba, 0x01, 0x33, 0x7c, 0x81, 0xeb, 0x61, 0x91, 0x81, 0xf3, 0x86, 0xfa, 0xa7, 0x21, 0x18, 0x6d, 0x05, 0x01, 0x35, 0xdd,
0xde, 0x68, 0xd0, 0x32, 0x38, 0x03, 0x4f, 0x36, 0xa6, 0xfb, 0xf4, 0x7d, 0xc6, 0x9a, 0xb1, 0x67, 0x8f, 0x6e, 0xc1, 0x14, 0x9f, 0x37, 0x1a, 0xb4, 0xda, 0x9c, 0x81, 0xe7, 0x1d, 0x93, 0x11, 0x7d,
0x46, 0xe3, 0x7b, 0x86, 0x67, 0x25, 0xed, 0x36, 0x0e, 0x02, 0xc1, 0xc2, 0xab, 0x0b, 0x0d, 0x41, 0x8f, 0xb1, 0x66, 0xec, 0x99, 0xe1, 0xf8, 0x9e, 0x41, 0x6b, 0x30, 0xee, 0xf7, 0x0e, 0x0e, 0xb0,
0xe4, 0x4c, 0x34, 0xda, 0x3b, 0xdd, 0x63, 0x93, 0xad, 0x10, 0x45, 0xe7, 0x0d, 0x9a, 0x38, 0x1c, 0xef, 0x0b, 0x16, 0x5e, 0x73, 0x68, 0x08, 0x22, 0x67, 0xa2, 0xd1, 0xde, 0xee, 0x1e, 0x1b, 0x6c,
0x60, 0x62, 0xb2, 0xb9, 0x55, 0x74, 0xf6, 0x4d, 0xe1, 0x7a, 0xee, 0x53, 0xd7, 0x7b, 0xe6, 0x1a, 0x85, 0x28, 0x3a, 0x6f, 0xd0, 0xc4, 0x61, 0x1f, 0x13, 0x83, 0xcd, 0xad, 0xa2, 0xb3, 0x6f, 0x0a,
0x5c, 0xa2, 0xca, 0x93, 0x1c, 0x41, 0x6c, 0x31, 0xc1, 0x2b, 0x10, 0xb6, 0x0d, 0x06, 0x30, 0xc1, 0xd7, 0x73, 0x3e, 0x73, 0xdc, 0x53, 0xa7, 0xcd, 0x25, 0xaa, 0xac, 0xb3, 0x21, 0x88, 0x2d, 0x26,
0x0b, 0x0d, 0x82, 0xb6, 0x4d, 0x71, 0x5e, 0x82, 0xea, 0xb1, 0x4d, 0x13, 0xab, 0xd3, 0x66, 0x2d, 0x78, 0x0d, 0x82, 0x76, 0x9b, 0x01, 0x8c, 0xf1, 0xf2, 0x83, 0xa0, 0x6d, 0x51, 0x9c, 0x17, 0xa1,
0xf5, 0x17, 0x8e, 0x05, 0x20, 0x3d, 0x64, 0xd3, 0xee, 0x43, 0xf3, 0x91, 0xdf, 0x0b, 0x08, 0xb6, 0x7a, 0x6c, 0xd1, 0x1c, 0xeb, 0xac, 0x59, 0x4b, 0xfd, 0x85, 0x63, 0x01, 0x48, 0x0f, 0xd8, 0xb4,
0xa2, 0x63, 0x46, 0x50, 0x3e, 0x82, 0xff, 0x4d, 0x81, 0xa5, 0x0c, 0x38, 0x11, 0x51, 0x9e, 0x00, 0x87, 0xd0, 0x7c, 0xe2, 0xf5, 0x7c, 0x82, 0xcd, 0xf0, 0x98, 0xe1, 0x97, 0x8f, 0xe0, 0x7f, 0x55,
0x22, 0xbc, 0xd3, 0x88, 0x82, 0x63, 0x20, 0x8e, 0x0b, 0x37, 0x63, 0xd8, 0xb9, 0x08, 0x9b, 0x34, 0x60, 0x21, 0x03, 0x4e, 0x44, 0x94, 0x67, 0x80, 0x08, 0xef, 0x6c, 0x87, 0xc1, 0xd1, 0x17, 0xc7,
0xb6, 0x3e, 0xd6, 0xef, 0xeb, 0xb3, 0x24, 0xc9, 0xa2, 0xde, 0x87, 0xaa, 0xe8, 0x45, 0xd7, 0xa1, 0x85, 0xdb, 0x31, 0xec, 0x5c, 0x84, 0x0d, 0x1a, 0x5b, 0x9f, 0xea, 0x0f, 0xf5, 0x69, 0x92, 0x64,
0x4a, 0x71, 0x0c, 0xf1, 0xbf, 0x4c, 0xc7, 0xe6, 0x0a, 0xed, 0xde, 0xb5, 0xe8, 0x2f, 0xcd, 0xb4, 0x51, 0x1f, 0x42, 0x55, 0xf4, 0xa2, 0x9b, 0x50, 0xa5, 0x38, 0x6d, 0xf1, 0xbf, 0x4c, 0xc7, 0xe6,
0xac, 0xe8, 0x0c, 0x51, 0xd3, 0xc3, 0xa6, 0x76, 0x07, 0xa6, 0x1f, 0x76, 0xb1, 0x6f, 0x12, 0xcf, 0x0a, 0xed, 0xde, 0x31, 0xe9, 0x2f, 0xcd, 0x30, 0xcd, 0xf0, 0x0c, 0x51, 0xd3, 0x83, 0xa6, 0x76,
0x2f, 0xef, 0x0d, 0x1b, 0x66, 0xfa, 0x20, 0xc2, 0x07, 0x73, 0x30, 0x8e, 0x3b, 0xa6, 0xed, 0x88, 0x0f, 0x26, 0x1f, 0x77, 0xb1, 0x67, 0x10, 0xd7, 0x2b, 0xef, 0x0d, 0x0b, 0xa6, 0x22, 0x10, 0xe1,
0x7f, 0x28, 0x6f, 0xd0, 0x1f, 0xfc, 0x33, 0xd3, 0x71, 0x30, 0x11, 0x7a, 0x88, 0x16, 0xba, 0x0e, 0x83, 0x19, 0x18, 0xc5, 0x1d, 0xc3, 0xb2, 0xc5, 0x3f, 0x94, 0x37, 0xe8, 0x0f, 0xfe, 0xd4, 0xb0,
0xd3, 0xfc, 0xcb, 0x38, 0xc4, 0x26, 0xe9, 0xf9, 0x2c, 0xfd, 0x1d, 0xdd, 0xa8, 0xe9, 0x53, 0x9c, 0x6d, 0x4c, 0x84, 0x1e, 0xa2, 0x85, 0x6e, 0xc2, 0x24, 0xff, 0x6a, 0x1f, 0x62, 0x83, 0xf4, 0x3c,
0xfc, 0x8e, 0xa0, 0x6a, 0x5f, 0x2a, 0xb0, 0x7a, 0x2f, 0x20, 0x76, 0x87, 0x6e, 0xb7, 0x3d, 0xf3, 0x96, 0x03, 0x0f, 0xaf, 0xd7, 0xf4, 0x09, 0x4e, 0x7e, 0x5b, 0x50, 0xb5, 0x2f, 0x15, 0x58, 0x79,
0xd4, 0xeb, 0x91, 0x8b, 0x39, 0xb4, 0xfe, 0x14, 0xd6, 0xf2, 0xf5, 0x10, 0x3e, 0xb8, 0x05, 0x08, 0xe0, 0x13, 0xab, 0x43, 0xb7, 0xdb, 0xae, 0x71, 0xe6, 0xf6, 0xc8, 0xe5, 0x1c, 0x5a, 0x7f, 0x0c,
0x87, 0x3c, 0x06, 0x36, 0x7d, 0xd7, 0x76, 0x8f, 0x02, 0x71, 0xb4, 0x99, 0x8d, 0x7a, 0xee, 0x89, 0xab, 0xf9, 0x7a, 0x08, 0x1f, 0xdc, 0x01, 0x84, 0x03, 0x9e, 0x36, 0x36, 0x3c, 0xc7, 0x72, 0x8e,
0x0e, 0xed, 0x3d, 0x58, 0x48, 0x40, 0x96, 0x9f, 0x92, 0x1d, 0x58, 0x4c, 0x61, 0x95, 0xd3, 0x6a, 0x7c, 0x71, 0xb4, 0x99, 0x0e, 0x7b, 0x1e, 0x88, 0x0e, 0xed, 0x5d, 0x98, 0x4b, 0x40, 0x96, 0x9f,
0x1b, 0xa6, 0x86, 0xce, 0x49, 0x76, 0x61, 0x3a, 0x99, 0x8c, 0xbc, 0x06, 0xf5, 0x2e, 0xd3, 0xcb, 0x92, 0x6d, 0x98, 0x4f, 0x61, 0x95, 0xd3, 0x6a, 0x0b, 0x26, 0x06, 0xce, 0x49, 0x76, 0x60, 0x32,
0xb0, 0xdd, 0x43, 0x4f, 0x20, 0xcd, 0xc7, 0x90, 0xb8, 0xd6, 0xbb, 0xee, 0xa1, 0xa7, 0x43, 0x37, 0x99, 0x8c, 0xbc, 0x0a, 0xf5, 0x2e, 0xd3, 0xab, 0x6d, 0x39, 0x87, 0xae, 0x40, 0x9a, 0x8d, 0x21,
0xfa, 0xd6, 0x3e, 0x85, 0x39, 0x01, 0xb5, 0x87, 0x7d, 0xdb, 0xb3, 0xca, 0x4f, 0xfa, 0x02, 0x54, 0x71, 0xad, 0x77, 0x9c, 0x43, 0x57, 0x87, 0x6e, 0xf8, 0xad, 0x7d, 0x02, 0x33, 0x02, 0x6a, 0x17,
0xba, 0x0c, 0x22, 0x5c, 0x8b, 0xbc, 0xa5, 0x3d, 0x84, 0xf9, 0xc4, 0x08, 0x43, 0xaa, 0xfc, 0x05, 0x7b, 0x96, 0x6b, 0x96, 0x9f, 0xf4, 0x39, 0xa8, 0x74, 0x19, 0x44, 0xb0, 0x16, 0x79, 0x4b, 0x7b,
0x2c, 0x5e, 0x68, 0x66, 0xaa, 0x43, 0x33, 0x37, 0x25, 0x2d, 0x6b, 0x13, 0xab, 0x93, 0x25, 0x40, 0x0c, 0xb3, 0x89, 0x11, 0x06, 0x54, 0xf9, 0x0b, 0x98, 0xbf, 0xd4, 0xcc, 0x54, 0x87, 0x66, 0x6e,
0x87, 0x9d, 0x90, 0x12, 0xe5, 0xc1, 0xfe, 0x1c, 0x8e, 0x4a, 0x73, 0xf8, 0x11, 0xac, 0xe4, 0x69, 0x4a, 0x5a, 0xd6, 0xa6, 0xdf, 0x29, 0xb0, 0x94, 0x04, 0x1d, 0x74, 0x42, 0x4a, 0x54, 0x0a, 0xa3,
0x37, 0xa4, 0xe1, 0x2d, 0x98, 0xa4, 0x5b, 0x03, 0x97, 0xb7, 0x53, 0xbb, 0x06, 0x53, 0x21, 0x44, 0x39, 0x1c, 0x96, 0xe6, 0xf0, 0x43, 0x58, 0xce, 0xd3, 0x6e, 0x40, 0xc3, 0x5b, 0x30, 0x4e, 0xb7,
0x3f, 0x58, 0xf6, 0x6b, 0xea, 0xa3, 0x3a, 0x6f, 0xb0, 0x78, 0xc0, 0xf8, 0x86, 0x5f, 0x36, 0xda, 0x06, 0x2e, 0x6f, 0xa7, 0x76, 0x03, 0x26, 0x02, 0x88, 0x28, 0x58, 0x46, 0x95, 0xf6, 0x61, 0x9d,
0xa7, 0xb0, 0x98, 0xc2, 0x12, 0x83, 0xdf, 0x83, 0x19, 0xcc, 0xba, 0xfa, 0x3f, 0x2b, 0xf1, 0xaf, 0x37, 0x58, 0x3c, 0x60, 0x7c, 0x83, 0x2f, 0x1b, 0xed, 0x13, 0x98, 0x4f, 0x61, 0x89, 0xc1, 0x1f,
0x52, 0xe3, 0x59, 0x69, 0x42, 0x7a, 0x1a, 0xcb, 0x04, 0xed, 0x63, 0x98, 0x4e, 0xf0, 0x64, 0x9b, 0xc0, 0x14, 0x66, 0x5d, 0xd1, 0xcf, 0x4a, 0xfc, 0xab, 0xd4, 0x78, 0x56, 0x9a, 0x90, 0x9e, 0xc4,
0x55, 0x66, 0x05, 0xef, 0xc0, 0xdc, 0x63, 0xd7, 0xb2, 0x03, 0xe2, 0xdb, 0x07, 0x3d, 0x32, 0x8c, 0x32, 0x41, 0xfb, 0x08, 0x26, 0x13, 0x3c, 0xd9, 0x66, 0x95, 0x59, 0xc1, 0xdb, 0x30, 0xf3, 0xd4,
0xef, 0x6f, 0xc1, 0x7c, 0x02, 0xa9, 0x70, 0x0a, 0xbe, 0x80, 0xc5, 0x3d, 0xf3, 0x34, 0x20, 0xbd, 0x31, 0x2d, 0x9f, 0x78, 0xd6, 0x7e, 0x8f, 0x0c, 0xe2, 0xfb, 0x3b, 0x30, 0x9b, 0x40, 0x2a, 0x9c,
0x83, 0x8b, 0xd9, 0xba, 0x3b, 0xd0, 0x4c, 0x8f, 0x2f, 0x34, 0xbe, 0x09, 0xd5, 0x2e, 0xef, 0x13, 0x82, 0x2f, 0x60, 0x7e, 0xd7, 0x38, 0xf3, 0x49, 0x6f, 0xff, 0x72, 0xb6, 0xee, 0x36, 0x34, 0xd3,
0x1a, 0x20, 0x79, 0xf5, 0xd2, 0x1e, 0x3d, 0x64, 0xa1, 0x61, 0x3c, 0xa4, 0x95, 0x76, 0xde, 0x4f, 0xe3, 0x0b, 0x8d, 0x6f, 0x43, 0xb5, 0xcb, 0xfb, 0x84, 0x06, 0x48, 0x5e, 0xbd, 0xb4, 0x47, 0x0f,
0x60, 0x3a, 0xc2, 0x28, 0xa5, 0xc4, 0xa7, 0x30, 0x27, 0x68, 0xdf, 0x56, 0xf0, 0xbe, 0x07, 0xf3, 0x58, 0x68, 0x18, 0x0f, 0x68, 0xa5, 0x9d, 0xf7, 0x23, 0x98, 0x0c, 0x31, 0x4a, 0x29, 0xf1, 0x09,
0x89, 0x11, 0x4a, 0x29, 0x4a, 0xc3, 0x5b, 0xd2, 0xf1, 0xdf, 0xa1, 0xf0, 0xf6, 0x01, 0xac, 0xe4, 0xcc, 0x08, 0xda, 0xb7, 0x15, 0xbc, 0x1f, 0xc0, 0x6c, 0x62, 0x84, 0x52, 0x8a, 0xd2, 0xf0, 0x96,
0x69, 0x57, 0xca, 0xdc, 0x57, 0x01, 0xfa, 0xe1, 0x8e, 0x1e, 0xdc, 0x8f, 0xb1, 0x13, 0x55, 0xfc, 0x74, 0xfc, 0x77, 0x28, 0xbc, 0xbd, 0x0f, 0xcb, 0x79, 0xda, 0x95, 0x32, 0xf7, 0x15, 0x80, 0x28,
0xe9, 0x37, 0xa5, 0xb1, 0xba, 0x0c, 0x2f, 0xc0, 0xb0, 0x6f, 0xed, 0x77, 0xa3, 0x50, 0x15, 0x50, 0xdc, 0xd1, 0x83, 0xfb, 0x31, 0xb6, 0xc3, 0x8a, 0x3f, 0xfd, 0xa6, 0x34, 0x56, 0x97, 0xe1, 0x05,
0x48, 0x83, 0x49, 0x5e, 0x1b, 0x13, 0x57, 0x76, 0xe1, 0xed, 0x20, 0x23, 0xb6, 0xd8, 0x5d, 0x1d, 0x18, 0xf6, 0xad, 0xfd, 0x66, 0x18, 0xaa, 0x02, 0x0a, 0x69, 0x30, 0xce, 0x6b, 0x63, 0xe2, 0x22,
0xba, 0x04, 0x35, 0xce, 0x73, 0x84, 0xc3, 0xc2, 0xd0, 0x04, 0x23, 0xbc, 0x8b, 0x09, 0xda, 0x80, 0x2f, 0xb8, 0x33, 0x64, 0xc4, 0x16, 0xbb, 0xc1, 0x43, 0x57, 0xa1, 0xc6, 0x79, 0x8e, 0x70, 0x50,
0x99, 0xa8, 0xd3, 0x10, 0x35, 0x25, 0x9e, 0x8e, 0x4c, 0x85, 0x3c, 0x3a, 0xaf, 0x2d, 0x5d, 0x83, 0x18, 0x1a, 0x63, 0x84, 0x77, 0x30, 0x41, 0xeb, 0x30, 0x15, 0x76, 0xb6, 0x45, 0x4d, 0x89, 0xa7,
0xe9, 0x3e, 0x27, 0xcf, 0xbd, 0x79, 0x52, 0x32, 0x19, 0x32, 0xf2, 0xe4, 0x68, 0x0d, 0x1a, 0x6d, 0x23, 0x13, 0x01, 0x8f, 0xce, 0x6b, 0x4b, 0x37, 0x60, 0x32, 0xe2, 0xe4, 0xb9, 0x37, 0x4f, 0x4a,
0xaf, 0xd3, 0x8d, 0x34, 0xe2, 0xd7, 0x9f, 0x40, 0x69, 0x42, 0xa1, 0x25, 0x98, 0x60, 0x1c, 0x54, 0xc6, 0x03, 0x46, 0x9e, 0x1c, 0xad, 0x42, 0xe3, 0xc0, 0xed, 0x74, 0x43, 0x8d, 0xf8, 0xa5, 0x28,
0x1f, 0x7e, 0xff, 0x59, 0xa5, 0x6d, 0xaa, 0xce, 0x35, 0x98, 0x0e, 0xbb, 0x42, 0x6d, 0xaa, 0x7c, 0x50, 0x9a, 0x50, 0x68, 0x01, 0xc6, 0x18, 0x07, 0xd5, 0x87, 0xdf, 0x8a, 0x56, 0x69, 0x9b, 0xaa,
0x10, 0xc1, 0x21, 0x94, 0xb9, 0x0a, 0x53, 0x11, 0x1f, 0xd7, 0x65, 0x82, 0x27, 0x48, 0x82, 0x8d, 0x73, 0x03, 0x26, 0x83, 0xae, 0x40, 0x9b, 0x2a, 0x1f, 0x44, 0x70, 0x08, 0x65, 0xae, 0xc3, 0x44,
0xab, 0x12, 0x7a, 0xb4, 0x96, 0xe1, 0x51, 0xe8, 0x7b, 0x14, 0xad, 0x41, 0x3d, 0x16, 0x9b, 0x9a, 0xc8, 0xc7, 0x75, 0x19, 0xe3, 0x09, 0x92, 0x60, 0xe3, 0xaa, 0x04, 0x1e, 0xad, 0x65, 0x78, 0x14,
0x75, 0xd6, 0x15, 0x27, 0x21, 0x15, 0x26, 0x2c, 0x3b, 0xe8, 0x7a, 0x01, 0xb6, 0x9a, 0x0d, 0xee, 0x22, 0x8f, 0xa2, 0x55, 0xa8, 0xc7, 0x62, 0x53, 0xb3, 0xce, 0xba, 0xe2, 0x24, 0xa4, 0xc2, 0x98,
0xc2, 0xb0, 0x4d, 0x53, 0x9c, 0x1d, 0xec, 0x58, 0xad, 0x0e, 0x4d, 0xca, 0x76, 0x78, 0xde, 0x53, 0x69, 0xf9, 0x5d, 0xd7, 0xc7, 0x66, 0xb3, 0xc1, 0x5d, 0x18, 0xb4, 0x69, 0x8a, 0xb3, 0x8d, 0x6d,
0x7e, 0xb3, 0x7f, 0x3d, 0x02, 0x4b, 0x19, 0x70, 0x62, 0x7d, 0xed, 0xf5, 0x13, 0x30, 0xfe, 0xaf, 0xb3, 0xd5, 0xa1, 0x49, 0xd9, 0x36, 0xcf, 0x7b, 0xca, 0x6f, 0xf6, 0xaf, 0x87, 0x60, 0x21, 0x03,
0x78, 0x2d, 0x06, 0x98, 0x2b, 0x96, 0xd1, 0x13, 0xc2, 0xa8, 0x6f, 0x02, 0xf4, 0x7b, 0x63, 0x2b, 0x4e, 0xac, 0xaf, 0xdd, 0x28, 0x01, 0xe3, 0xff, 0x8a, 0x57, 0x63, 0x80, 0xb9, 0x62, 0x19, 0x3d,
0x5f, 0x89, 0xaf, 0x7c, 0x4a, 0x37, 0x3b, 0x51, 0x05, 0x68, 0x54, 0x17, 0x2d, 0xf5, 0x2b, 0x05, 0x01, 0x8c, 0xfa, 0x06, 0x40, 0xd4, 0x1b, 0x5b, 0xf9, 0x4a, 0x7c, 0xe5, 0x53, 0xba, 0xd1, 0x09,
0x66, 0x53, 0xe0, 0xa9, 0x2d, 0xa7, 0x0c, 0xde, 0x72, 0x3a, 0x34, 0xe8, 0xf4, 0x18, 0x1c, 0x97, 0x2b, 0x40, 0xc3, 0xba, 0x68, 0xa9, 0x5f, 0x29, 0x30, 0x9d, 0x02, 0x4f, 0x6d, 0x39, 0xa5, 0xff,
0xe6, 0x4b, 0xd4, 0xba, 0xdb, 0xe7, 0xb4, 0x4e, 0xaf, 0x1f, 0x47, 0xdf, 0x81, 0xf6, 0x10, 0x2e, 0x96, 0xd3, 0xa1, 0x41, 0xa7, 0xa7, 0xcd, 0x71, 0x69, 0xbe, 0x44, 0xad, 0xbb, 0x7b, 0x41, 0xeb,
0x25, 0x0e, 0xe3, 0xec, 0xde, 0xba, 0xfc, 0xdc, 0x3c, 0x80, 0xe5, 0x6c, 0xc0, 0x72, 0x47, 0xfc, 0xf4, 0xfa, 0x71, 0xf8, 0xed, 0x6b, 0x8f, 0xe1, 0x6a, 0xe2, 0x30, 0xce, 0x6e, 0xb3, 0xcb, 0xcf,
0x87, 0x70, 0xa9, 0xe5, 0x38, 0xfd, 0x1c, 0x73, 0xe8, 0xf3, 0xfe, 0x87, 0xb0, 0x9c, 0x0d, 0x38, 0xcd, 0x23, 0x58, 0xcc, 0x06, 0x2c, 0x77, 0xc4, 0x7f, 0x0c, 0x57, 0x5b, 0xb6, 0x1d, 0xe5, 0x98,
0xe4, 0xe1, 0xab, 0x03, 0x57, 0x24, 0x5c, 0x1e, 0xf4, 0x86, 0x55, 0x37, 0xf7, 0x67, 0xf2, 0x73, 0x03, 0x9f, 0xf7, 0x3f, 0x80, 0xc5, 0x6c, 0xc0, 0x01, 0x0f, 0x5f, 0x1d, 0xb8, 0x26, 0xe1, 0xf2,
0xd0, 0x8a, 0x86, 0x7b, 0x0e, 0x69, 0x41, 0x08, 0x3d, 0xb4, 0x09, 0x25, 0xd3, 0x82, 0xd4, 0xf8, 0xa0, 0x37, 0xa8, 0xba, 0xb9, 0x3f, 0x93, 0x9f, 0x82, 0x56, 0x34, 0xdc, 0x73, 0x48, 0x0b, 0x02,
0xcf, 0x23, 0x2d, 0x90, 0x7f, 0x49, 0x17, 0x60, 0x5a, 0x61, 0x5a, 0x90, 0xa3, 0xdd, 0x90, 0x86, 0xe8, 0x81, 0x4d, 0x28, 0x99, 0x16, 0xa4, 0xc6, 0x7f, 0x1e, 0x69, 0x81, 0xfc, 0x4b, 0xba, 0x04,
0x3f, 0x80, 0x25, 0x7e, 0xfa, 0xdd, 0xc3, 0xfe, 0x73, 0x38, 0xae, 0xb7, 0x41, 0xcd, 0x82, 0x7b, 0xd3, 0x0a, 0xd3, 0x82, 0x1c, 0xed, 0x06, 0x34, 0xfc, 0x11, 0x2c, 0xf0, 0xd3, 0xef, 0x2e, 0xf6,
0xbe, 0x27, 0xf6, 0xf8, 0x02, 0x1c, 0xf6, 0x6c, 0x58, 0xf2, 0x70, 0x9b, 0x1e, 0xbf, 0xf4, 0xb9, 0x9e, 0xc3, 0x71, 0xfd, 0x00, 0xd4, 0x2c, 0xb8, 0xe7, 0x7b, 0x62, 0x8f, 0x2f, 0xc0, 0x41, 0xcf,
0x92, 0x4d, 0xe7, 0xd0, 0x66, 0x14, 0x9d, 0x2b, 0xe5, 0x11, 0x4a, 0x9f, 0x2b, 0x13, 0x2b, 0xf0, 0x86, 0x25, 0x0f, 0xb7, 0xe9, 0xf1, 0x4b, 0x9f, 0x2b, 0xd9, 0x74, 0x0e, 0x6c, 0x46, 0xd1, 0xb9,
0x02, 0x3c, 0x5f, 0x74, 0xae, 0xcc, 0xd3, 0xae, 0x8c, 0xb9, 0x5b, 0xbf, 0x1a, 0x81, 0xaa, 0x78, 0x52, 0x1e, 0xa1, 0xf4, 0xb9, 0x32, 0xb1, 0x02, 0x2f, 0xc1, 0xf3, 0x45, 0xe7, 0xca, 0x3c, 0xed,
0x0c, 0x83, 0xde, 0x81, 0x5a, 0xf4, 0x22, 0x0e, 0x5d, 0x8a, 0x49, 0x25, 0x9f, 0xdb, 0xa9, 0xcb, 0xca, 0x98, 0xbb, 0xf9, 0x8b, 0x21, 0xa8, 0x8a, 0x77, 0x31, 0xe8, 0x6d, 0xa8, 0x85, 0xef, 0xe4,
0xd9, 0x9d, 0x42, 0x83, 0x1d, 0x18, 0xe7, 0x4f, 0x69, 0x56, 0xf2, 0x5e, 0xdc, 0x08, 0x98, 0xd5, 0xd0, 0xd5, 0x98, 0x54, 0xf2, 0x11, 0x9e, 0xba, 0x98, 0xdd, 0x29, 0x34, 0xd8, 0x86, 0x51, 0xfe,
0xdc, 0x7e, 0x81, 0xd4, 0x86, 0x29, 0xf9, 0x8d, 0x0f, 0xba, 0x9e, 0x23, 0x92, 0xdc, 0xd1, 0xea, 0xaa, 0x66, 0x39, 0xef, 0xf1, 0x8d, 0x80, 0x59, 0xc9, 0xed, 0x17, 0x48, 0x07, 0x30, 0x21, 0x3f,
0xc6, 0x60, 0x46, 0x3e, 0xc8, 0xd6, 0xbf, 0x2a, 0x50, 0x8b, 0x5e, 0x85, 0x20, 0x13, 0x1a, 0xf1, 0xf7, 0x41, 0x37, 0x73, 0x44, 0x92, 0x3b, 0x5a, 0x5d, 0xef, 0xcf, 0xc8, 0x07, 0xd9, 0xfc, 0x67,
0x47, 0x36, 0xd2, 0x80, 0x45, 0x0f, 0x7b, 0xa4, 0x01, 0x8b, 0xdf, 0xeb, 0x9c, 0xc0, 0x52, 0xee, 0x05, 0x6a, 0xe1, 0xab, 0x10, 0x64, 0x40, 0x23, 0xfe, 0xc8, 0x46, 0x1a, 0xb0, 0xe8, 0x61, 0x8f,
0x8b, 0x18, 0xf4, 0x62, 0x16, 0x4c, 0x4e, 0x71, 0x4a, 0xbd, 0x79, 0x36, 0xe6, 0xa8, 0xe8, 0x3d, 0x34, 0x60, 0xf1, 0x7b, 0x9d, 0x13, 0x58, 0xc8, 0x7d, 0x11, 0x83, 0x5e, 0xc8, 0x82, 0xc9, 0x29,
0x93, 0x64, 0x42, 0x5a, 0x01, 0x42, 0x38, 0xca, 0x7a, 0x21, 0x8f, 0x00, 0xef, 0xc0, 0x42, 0xf6, 0x4e, 0xa9, 0xb7, 0xcf, 0xc7, 0x1c, 0x16, 0xbd, 0xa7, 0x92, 0x4c, 0x48, 0x2b, 0x40, 0x08, 0x46,
0xeb, 0x14, 0xb4, 0x91, 0xba, 0x39, 0xcf, 0x33, 0xe7, 0xc6, 0x19, 0x38, 0xc5, 0x70, 0x3a, 0x4c, 0x59, 0x2b, 0xe4, 0x11, 0xe0, 0x1d, 0x98, 0xcb, 0x7e, 0x9d, 0x82, 0xd6, 0x53, 0x37, 0xe7, 0x79,
0x4a, 0x1c, 0x68, 0x35, 0x4f, 0x36, 0x04, 0x5f, 0xcb, 0x67, 0x10, 0x98, 0x5d, 0x58, 0xcc, 0x79, 0xe6, 0xdc, 0x3a, 0x07, 0xa7, 0x18, 0x4e, 0x87, 0x71, 0x89, 0x03, 0xad, 0xe4, 0xc9, 0x06, 0xe0,
0x1f, 0x82, 0x6e, 0xa4, 0x6f, 0xf4, 0xf3, 0x8c, 0xf8, 0xc1, 0x59, 0x58, 0xc5, 0x88, 0x8f, 0x61, 0xab, 0xf9, 0x0c, 0x02, 0xb3, 0x0b, 0xf3, 0x39, 0xef, 0x43, 0xd0, 0xad, 0xf4, 0x8d, 0x7e, 0x9e,
0x4a, 0x66, 0x41, 0x6b, 0xb9, 0xd2, 0x21, 0xfe, 0x95, 0x02, 0x8e, 0x3e, 0xac, 0xfc, 0x5c, 0x43, 0x11, 0xdf, 0x3b, 0x0f, 0xab, 0x18, 0xf1, 0x29, 0x4c, 0xc8, 0x2c, 0x68, 0x35, 0x57, 0x3a, 0xc0,
0x82, 0xcd, 0x7c, 0x47, 0x22, 0xc1, 0xe6, 0xbc, 0xf5, 0x78, 0x03, 0xc6, 0x59, 0x0f, 0x5a, 0x4c, 0xbf, 0x56, 0xc0, 0x11, 0xc1, 0xca, 0xcf, 0x35, 0x24, 0xd8, 0xcc, 0x77, 0x24, 0x12, 0x6c, 0xce,
0xf2, 0x86, 0x20, 0xcd, 0x74, 0x87, 0xd8, 0x64, 0x5f, 0x8e, 0xc2, 0x18, 0x8d, 0x73, 0xe8, 0x6d, 0x5b, 0x8f, 0xd7, 0x61, 0x94, 0xf5, 0xa0, 0xf9, 0x24, 0x6f, 0x00, 0xd2, 0x4c, 0x77, 0x88, 0x4d,
0xa8, 0x8a, 0xeb, 0x7c, 0xb4, 0x14, 0xe3, 0x96, 0x9f, 0x09, 0xa8, 0x6a, 0x56, 0x97, 0x50, 0xe3, 0xf6, 0xe5, 0x30, 0x8c, 0xd0, 0x38, 0x87, 0xde, 0x82, 0xaa, 0xb8, 0xce, 0x47, 0x0b, 0x31, 0x6e,
0x3e, 0xd4, 0x63, 0x77, 0xf3, 0xe8, 0x72, 0x8c, 0x35, 0x7d, 0xf7, 0xaf, 0xae, 0xe4, 0x75, 0x0b, 0xf9, 0x99, 0x80, 0xaa, 0x66, 0x75, 0x09, 0x35, 0x1e, 0x42, 0x3d, 0x76, 0x37, 0x8f, 0x96, 0x62,
0xb4, 0x5d, 0x80, 0xfe, 0x2d, 0x30, 0x5a, 0xce, 0xb9, 0x1c, 0xe6, 0x58, 0x97, 0x0b, 0xaf, 0x8e, 0xac, 0xe9, 0xbb, 0x7f, 0x75, 0x39, 0xaf, 0x5b, 0xa0, 0xed, 0x00, 0x44, 0xb7, 0xc0, 0x68, 0x31,
0xd1, 0x27, 0x30, 0x9b, 0xba, 0x2f, 0x42, 0xeb, 0xc5, 0xb7, 0x49, 0x1c, 0xf8, 0xea, 0x59, 0xae, 0xe7, 0x72, 0x98, 0x63, 0x2d, 0x15, 0x5e, 0x1d, 0xa3, 0x8f, 0x61, 0x3a, 0x75, 0x5f, 0x84, 0xd6,
0x9c, 0xd0, 0x1d, 0x98, 0x08, 0x2f, 0x71, 0x50, 0xdc, 0x41, 0x89, 0xeb, 0x21, 0xf5, 0x52, 0x66, 0x8a, 0x6f, 0x93, 0x38, 0xf0, 0xf5, 0xf3, 0x5c, 0x39, 0xa1, 0x7b, 0x30, 0x16, 0x5c, 0xe2, 0xa0,
0x9f, 0x98, 0x88, 0x7f, 0xd7, 0x58, 0x49, 0xc0, 0xeb, 0x91, 0x80, 0xce, 0x45, 0xb8, 0xee, 0xe2, 0xb8, 0x83, 0x12, 0xd7, 0x43, 0xea, 0xd5, 0xcc, 0x3e, 0x31, 0x11, 0xff, 0xaa, 0xb1, 0x92, 0x80,
0x73, 0x91, 0x58, 0x70, 0x6a, 0x56, 0x57, 0x7f, 0x1b, 0x4a, 0x95, 0x78, 0x69, 0x1b, 0x66, 0xdd, 0xdb, 0x23, 0x3e, 0x9d, 0x8b, 0x60, 0xdd, 0xc5, 0xe7, 0x22, 0xb1, 0xe0, 0xd4, 0xac, 0xae, 0x68,
0x02, 0x48, 0xdb, 0x30, 0xbb, 0x88, 0xff, 0x04, 0x66, 0x52, 0xfb, 0x4f, 0x4b, 0x4b, 0xa5, 0x56, 0x1b, 0x4a, 0x95, 0x78, 0x69, 0x1b, 0x66, 0xdd, 0x02, 0x48, 0xdb, 0x30, 0xbb, 0x88, 0xff, 0x0c,
0xf0, 0x7a, 0x21, 0x4f, 0x3f, 0x4c, 0x65, 0x97, 0x9d, 0xa5, 0x30, 0x55, 0x58, 0x37, 0x97, 0xc2, 0xa6, 0x52, 0xfb, 0x4f, 0x4b, 0x4b, 0xa5, 0x56, 0xf0, 0x5a, 0x21, 0x4f, 0x14, 0xa6, 0xb2, 0xcb,
0xd4, 0x80, 0x1a, 0xf6, 0x5b, 0x50, 0xe1, 0x87, 0x3c, 0xd4, 0x4c, 0x9d, 0xfb, 0x42, 0xb8, 0xa5, 0xce, 0x52, 0x98, 0x2a, 0xac, 0x9b, 0x4b, 0x61, 0xaa, 0x4f, 0x0d, 0xfb, 0x4d, 0xa8, 0xf0, 0x43,
0x8c, 0x1e, 0x21, 0xfe, 0x51, 0xba, 0x62, 0x7b, 0xa5, 0xe0, 0xfc, 0x28, 0x00, 0xb5, 0x22, 0x16, 0x1e, 0x6a, 0xa6, 0xce, 0x7d, 0x01, 0xdc, 0x42, 0x46, 0x8f, 0x10, 0xff, 0x30, 0x5d, 0xb1, 0xbd,
0x81, 0x1c, 0x40, 0x33, 0xef, 0x72, 0x0c, 0xc5, 0x23, 0xd8, 0x80, 0x9b, 0x3c, 0xf5, 0xc5, 0x33, 0x56, 0x70, 0x7e, 0x14, 0x80, 0x5a, 0x11, 0x8b, 0x40, 0xf6, 0xa1, 0x99, 0x77, 0x39, 0x86, 0xe2,
0xf1, 0xc6, 0xcc, 0x91, 0x79, 0x64, 0x73, 0x32, 0xaf, 0xd6, 0x64, 0x73, 0x72, 0x6e, 0xcc, 0x74, 0x11, 0xac, 0xcf, 0x4d, 0x9e, 0xfa, 0xc2, 0xb9, 0x78, 0x63, 0xe6, 0xc8, 0x3c, 0xb2, 0x39, 0x99,
0x98, 0x94, 0x8a, 0xc6, 0xd2, 0x3a, 0xcc, 0x2a, 0x4c, 0x4b, 0xeb, 0x30, 0xbb, 0xde, 0xfc, 0x04, 0x57, 0x6b, 0xb2, 0x39, 0x39, 0x37, 0x66, 0x3a, 0x8c, 0x4b, 0x45, 0x63, 0x69, 0x1d, 0x66, 0x15,
0x66, 0x92, 0x25, 0x3c, 0x69, 0x1d, 0xe6, 0x94, 0x9d, 0xa5, 0x75, 0x98, 0x5b, 0x1a, 0x7e, 0xbb, 0xa6, 0xa5, 0x75, 0x98, 0x5d, 0x6f, 0x7e, 0x06, 0x53, 0xc9, 0x12, 0x9e, 0xb4, 0x0e, 0x73, 0xca,
0x5f, 0x98, 0x5b, 0xca, 0x38, 0x9f, 0x65, 0x6c, 0xbd, 0xe4, 0x39, 0x4f, 0x87, 0x49, 0xa9, 0x8e, 0xce, 0xd2, 0x3a, 0xcc, 0x2d, 0x0d, 0xbf, 0x15, 0x15, 0xe6, 0x16, 0x32, 0xce, 0x67, 0x19, 0x5b,
0x2a, 0x99, 0x9c, 0x55, 0xc3, 0x95, 0x4c, 0xce, 0x2e, 0xc1, 0x76, 0x60, 0x21, 0xbb, 0x6a, 0x29, 0x2f, 0x79, 0xce, 0xd3, 0x61, 0x5c, 0xaa, 0xa3, 0x4a, 0x26, 0x67, 0xd5, 0x70, 0x25, 0x93, 0xb3,
0xed, 0x8e, 0xc2, 0xb2, 0xab, 0xb4, 0x3b, 0x06, 0x94, 0x40, 0x3f, 0xc9, 0xaa, 0x08, 0xad, 0x17, 0x4b, 0xb0, 0x1d, 0x98, 0xcb, 0xae, 0x5a, 0x4a, 0xbb, 0xa3, 0xb0, 0xec, 0x2a, 0xed, 0x8e, 0x3e,
0x17, 0x72, 0xd2, 0x01, 0x33, 0xb7, 0xda, 0xb3, 0xf5, 0x9f, 0x1a, 0x54, 0xc4, 0x3a, 0x3b, 0x82, 0x25, 0xd0, 0x8f, 0xb3, 0x2a, 0x42, 0x6b, 0xc5, 0x85, 0x9c, 0x74, 0xc0, 0xcc, 0xad, 0xf6, 0x6c,
0xb9, 0xac, 0x7a, 0x07, 0xba, 0x16, 0x7f, 0x95, 0x90, 0x5f, 0x61, 0x51, 0xaf, 0x0f, 0xe4, 0x13, 0xfe, 0xbb, 0x06, 0x15, 0xb1, 0xce, 0x8e, 0x60, 0x26, 0xab, 0xde, 0x81, 0x6e, 0xc4, 0x5f, 0x25,
0x36, 0x9d, 0x82, 0x9a, 0x5f, 0x91, 0x40, 0x37, 0xf3, 0x60, 0xb2, 0x32, 0x71, 0xf5, 0xd6, 0x19, 0xe4, 0x57, 0x58, 0xd4, 0x9b, 0x7d, 0xf9, 0x84, 0x4d, 0x67, 0xa0, 0xe6, 0x57, 0x24, 0xd0, 0xed,
0xb9, 0x63, 0x81, 0x33, 0x51, 0x2e, 0x90, 0x03, 0x67, 0x76, 0x2d, 0x43, 0x0e, 0x9c, 0x79, 0xf5, 0x3c, 0x98, 0xac, 0x4c, 0x5c, 0xbd, 0x73, 0x4e, 0xee, 0x58, 0xe0, 0x4c, 0x94, 0x0b, 0xe4, 0xc0,
0x06, 0x1a, 0x38, 0x33, 0x13, 0x73, 0x39, 0x70, 0x16, 0x55, 0x16, 0xe4, 0xc0, 0x59, 0x9c, 0xe5, 0x99, 0x5d, 0xcb, 0x90, 0x03, 0x67, 0x5e, 0xbd, 0x81, 0x06, 0xce, 0xcc, 0xc4, 0x5c, 0x0e, 0x9c,
0x0f, 0x19, 0x38, 0x4d, 0x40, 0xe9, 0xec, 0x1c, 0x5d, 0x4d, 0x09, 0x64, 0xd4, 0x02, 0xd4, 0xef, 0x45, 0x95, 0x05, 0x39, 0x70, 0x16, 0x67, 0xf9, 0x03, 0x06, 0x4e, 0x03, 0x50, 0x3a, 0x3b, 0x47,
0x0f, 0xe0, 0xba, 0xc8, 0x08, 0x7a, 0x04, 0x73, 0x59, 0x65, 0x45, 0x69, 0x19, 0x17, 0x14, 0x32, 0xd7, 0x53, 0x02, 0x19, 0xb5, 0x00, 0xf5, 0xff, 0xfb, 0x70, 0x5d, 0x66, 0x04, 0x3d, 0x82, 0x99,
0xa5, 0x65, 0x5c, 0x58, 0x9f, 0xfc, 0x96, 0x02, 0x6a, 0xb2, 0x9a, 0x90, 0xbd, 0x3e, 0x13, 0x51, 0xac, 0xb2, 0xa2, 0xb4, 0x8c, 0x0b, 0x0a, 0x99, 0xd2, 0x32, 0x2e, 0xac, 0x4f, 0x7e, 0x4b, 0x01,
0x70, 0xbd, 0x90, 0xe7, 0xb9, 0x06, 0xd4, 0x78, 0x46, 0x2d, 0x07, 0xd4, 0x8c, 0x4a, 0x80, 0x1c, 0x35, 0x59, 0x4d, 0xc8, 0x5e, 0x9f, 0x89, 0x28, 0xb8, 0x56, 0xc8, 0xf3, 0x5c, 0x03, 0x6a, 0x3c,
0x50, 0x33, 0x93, 0xf1, 0xf4, 0xae, 0x09, 0xc1, 0x0b, 0x76, 0x4d, 0x62, 0x94, 0x1b, 0x67, 0xe0, 0xa3, 0x96, 0x03, 0x6a, 0x46, 0x25, 0x40, 0x0e, 0xa8, 0x99, 0xc9, 0x78, 0x7a, 0xd7, 0x04, 0xe0,
0xe4, 0xc3, 0x6d, 0x5f, 0xfd, 0x58, 0xa3, 0x11, 0xf0, 0xb3, 0x4d, 0xdb, 0xbb, 0xcd, 0x3e, 0x6e, 0x05, 0xbb, 0x26, 0x31, 0xca, 0xad, 0x73, 0x70, 0xf2, 0xe1, 0xb6, 0xae, 0x7f, 0xa4, 0xd1, 0x08,
0x77, 0x7d, 0xfb, 0xc4, 0x24, 0xf8, 0x76, 0x04, 0xd1, 0x3d, 0x38, 0xa8, 0xb0, 0x57, 0x6e, 0xaf, 0xf8, 0xe9, 0x86, 0xe5, 0xde, 0x65, 0x1f, 0x77, 0xbb, 0x9e, 0x75, 0x62, 0x10, 0x7c, 0x37, 0x84,
0xfc, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xcd, 0xbd, 0x5b, 0xbc, 0x37, 0x00, 0x00, 0xe8, 0xee, 0xef, 0x57, 0xd8, 0x2b, 0xb7, 0x97, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xde, 0x43,
0x56, 0xb1, 0xd2, 0x37, 0x00, 0x00,
} }

View File

@ -47,7 +47,7 @@ message StorageUsageRequest {
message StorageUsageResponse { message StorageUsageResponse {
repeated StorageUsage storage_usage = 1; repeated StorageUsage storage_usage = 1;
double summary = 2; double summary = 2;
double summary_bytes = 3; double average_usage_bytes = 3;
} }
message StorageUsageSatelliteRequest { message StorageUsageSatelliteRequest {
@ -60,7 +60,7 @@ message StorageUsageSatelliteRequest {
message StorageUsageSatelliteResponse { message StorageUsageSatelliteResponse {
repeated StorageUsage storage_usage = 1; repeated StorageUsage storage_usage = 1;
double summary = 2; double summary = 2;
double summary_bytes = 3; double average_usage_bytes = 3;
} }
service Bandwidth { service Bandwidth {

View File

@ -256,6 +256,7 @@ type Satellite struct {
StorageDaily []storageusage.Stamp `json:"storageDaily"` StorageDaily []storageusage.Stamp `json:"storageDaily"`
BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"` BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"`
StorageSummary float64 `json:"storageSummary"` StorageSummary float64 `json:"storageSummary"`
AverageUsageBytes float64 `json:"averageUsageBytes"`
BandwidthSummary int64 `json:"bandwidthSummary"` BandwidthSummary int64 `json:"bandwidthSummary"`
EgressSummary int64 `json:"egressSummary"` EgressSummary int64 `json:"egressSummary"`
IngressSummary int64 `json:"ingressSummary"` IngressSummary int64 `json:"ingressSummary"`
@ -296,7 +297,7 @@ func (s *Service) GetSatelliteData(ctx context.Context, satelliteID storj.NodeID
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
} }
storageSummary, err := s.storageUsageDB.SatelliteSummary(ctx, satelliteID, from, to) storageSummary, averageUsageInBytes, err := s.storageUsageDB.SatelliteSummary(ctx, satelliteID, from, to)
if err != nil { if err != nil {
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
} }
@ -334,6 +335,7 @@ func (s *Service) GetSatelliteData(ctx context.Context, satelliteID storj.NodeID
StorageDaily: storageDaily, StorageDaily: storageDaily,
BandwidthDaily: bandwidthDaily, BandwidthDaily: bandwidthDaily,
StorageSummary: storageSummary, StorageSummary: storageSummary,
AverageUsageBytes: averageUsageInBytes,
BandwidthSummary: bandwidthSummary.Total(), BandwidthSummary: bandwidthSummary.Total(),
CurrentStorageUsed: currentStorageUsed, CurrentStorageUsed: currentStorageUsed,
EgressSummary: egressSummary.Total(), EgressSummary: egressSummary.Total(),
@ -352,14 +354,15 @@ func (s *Service) GetSatelliteData(ctx context.Context, satelliteID storj.NodeID
// Satellites represents consolidated data across all satellites. // Satellites represents consolidated data across all satellites.
type Satellites struct { type Satellites struct {
StorageDaily []storageusage.Stamp `json:"storageDaily"` StorageDaily []storageusage.Stamp `json:"storageDaily"`
BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"` BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"`
StorageSummary float64 `json:"storageSummary"` StorageSummary float64 `json:"storageSummary"`
BandwidthSummary int64 `json:"bandwidthSummary"` AverageUsageBytes float64 `json:"averageUsageBytes"`
EgressSummary int64 `json:"egressSummary"` BandwidthSummary int64 `json:"bandwidthSummary"`
IngressSummary int64 `json:"ingressSummary"` EgressSummary int64 `json:"egressSummary"`
EarliestJoinedAt time.Time `json:"earliestJoinedAt"` IngressSummary int64 `json:"ingressSummary"`
Audits []Audits `json:"audits"` EarliestJoinedAt time.Time `json:"earliestJoinedAt"`
Audits []Audits `json:"audits"`
} }
// Audits represents audit, suspension and online scores of SNO across all satellites. // Audits represents audit, suspension and online scores of SNO across all satellites.
@ -403,7 +406,7 @@ func (s *Service) GetAllSatellitesData(ctx context.Context) (_ *Satellites, err
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
} }
storageSummary, err := s.storageUsageDB.Summary(ctx, from, to) storageSummary, averageUsageInBytes, err := s.storageUsageDB.Summary(ctx, from, to)
if err != nil { if err != nil {
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
} }
@ -436,14 +439,15 @@ func (s *Service) GetAllSatellitesData(ctx context.Context) (_ *Satellites, err
} }
return &Satellites{ return &Satellites{
StorageDaily: storageDaily, StorageDaily: storageDaily,
BandwidthDaily: bandwidthDaily, BandwidthDaily: bandwidthDaily,
StorageSummary: storageSummary, StorageSummary: storageSummary,
BandwidthSummary: bandwidthSummary.Total(), AverageUsageBytes: averageUsageInBytes,
EgressSummary: egressSummary.Total(), BandwidthSummary: bandwidthSummary.Total(),
IngressSummary: ingressSummary.Total(), EgressSummary: egressSummary.Total(),
EarliestJoinedAt: joinedAt, IngressSummary: ingressSummary.Total(),
Audits: audits, EarliestJoinedAt: joinedAt,
Audits: audits,
}, nil }, nil
} }

View File

@ -85,7 +85,7 @@ func (storage *StorageEndpoint) Usage(ctx context.Context, req *multinodepb.Stor
if err != nil { if err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Internal, err) return nil, rpcstatus.Wrap(rpcstatus.Internal, err)
} }
summary, err := storage.usage.Summary(ctx, from, to) summary, averageUsageInBytes, err := storage.usage.Summary(ctx, from, to)
if err != nil { if err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Internal, err) return nil, rpcstatus.Wrap(rpcstatus.Internal, err)
} }
@ -93,14 +93,16 @@ func (storage *StorageEndpoint) Usage(ctx context.Context, req *multinodepb.Stor
var usage []*multinodepb.StorageUsage var usage []*multinodepb.StorageUsage
for _, stamp := range stamps { for _, stamp := range stamps {
usage = append(usage, &multinodepb.StorageUsage{ usage = append(usage, &multinodepb.StorageUsage{
AtRestTotal: stamp.AtRestTotal, AtRestTotal: stamp.AtRestTotal,
IntervalStart: stamp.IntervalStart, AtRestTotalBytes: stamp.AtRestTotalBytes,
IntervalStart: stamp.IntervalStart,
}) })
} }
return &multinodepb.StorageUsageResponse{ return &multinodepb.StorageUsageResponse{
StorageUsage: usage, StorageUsage: usage,
Summary: summary, Summary: summary,
AverageUsageBytes: averageUsageInBytes,
}, nil }, nil
} }
@ -129,7 +131,7 @@ func (storage *StorageEndpoint) UsageSatellite(ctx context.Context, req *multino
if err != nil { if err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Internal, err) return nil, rpcstatus.Wrap(rpcstatus.Internal, err)
} }
summary, err := storage.usage.SatelliteSummary(ctx, req.SatelliteId, from, to) summary, averageUsageInBytes, err := storage.usage.SatelliteSummary(ctx, req.SatelliteId, from, to)
if err != nil { if err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Internal, err) return nil, rpcstatus.Wrap(rpcstatus.Internal, err)
} }
@ -137,13 +139,15 @@ func (storage *StorageEndpoint) UsageSatellite(ctx context.Context, req *multino
var usage []*multinodepb.StorageUsage var usage []*multinodepb.StorageUsage
for _, stamp := range stamps { for _, stamp := range stamps {
usage = append(usage, &multinodepb.StorageUsage{ usage = append(usage, &multinodepb.StorageUsage{
AtRestTotal: stamp.AtRestTotal, AtRestTotal: stamp.AtRestTotal,
IntervalStart: stamp.IntervalStart, AtRestTotalBytes: stamp.AtRestTotalBytes,
IntervalStart: stamp.IntervalStart,
}) })
} }
return &multinodepb.StorageUsageSatelliteResponse{ return &multinodepb.StorageUsageSatelliteResponse{
StorageUsage: usage, StorageUsage: usage,
Summary: summary, Summary: summary,
AverageUsageBytes: averageUsageInBytes,
}, nil }, nil
} }

View File

@ -150,8 +150,8 @@ func (s *Service) estimationUsagePeriod(ctx context.Context, period time.Time, j
for j := 0; j < len(storageDaily); j++ { for j := 0; j < len(storageDaily); j++ {
payout.DiskSpace += storageDaily[j].AtRestTotal payout.DiskSpace += storageDaily[j].AtRestTotal
} }
// dividing by 30 to show tbm instead of tb. // dividing by 720 to show tbm instead of tbh.
payout.DiskSpace /= 30 payout.DiskSpace /= 720
payout.SetDiskSpacePayout(priceModel.DiskSpace) payout.SetDiskSpacePayout(priceModel.DiskSpace)
payout.SetHeldAmount() payout.SetHeldAmount()
payout.SetPayout() payout.SetPayout()

View File

@ -19,14 +19,23 @@ func MakeStorageUsageStamps(satellites []storj.NodeID, days int, endDate time.Ti
startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day()-days, 0, 0, 0, 0, endDate.Location()) startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day()-days, 0, 0, 0, 0, endDate.Location())
for _, satellite := range satellites { for _, satellite := range satellites {
previousStampIntervalEndTime := startDate
for i := 0; i < days; i++ { for i := 0; i < days; i++ {
h := testrand.Intn(24) h := testrand.Intn(24)
intervalEndTime := startDate.Add(time.Hour * 24 * time.Duration(i)).Add(time.Hour * time.Duration(h)) intervalEndTime := startDate.Add(time.Hour * 24 * time.Duration(i)).Add(time.Hour * time.Duration(h))
atRestTotalBytes := math.Round(testrand.Float64n(100))
intervalInHours := float64(24)
if i > 0 {
intervalInHours = intervalEndTime.Sub(previousStampIntervalEndTime).Hours()
}
previousStampIntervalEndTime = intervalEndTime
stamp := storageusage.Stamp{ stamp := storageusage.Stamp{
SatelliteID: satellite, SatelliteID: satellite,
AtRestTotal: math.Round(testrand.Float64n(1000)), AtRestTotalBytes: atRestTotalBytes,
IntervalStart: time.Date(intervalEndTime.Year(), intervalEndTime.Month(), intervalEndTime.Day(), 0, 0, 0, 0, intervalEndTime.Location()), AtRestTotal: atRestTotalBytes * intervalInHours,
IntervalEndTime: intervalEndTime, IntervalInHours: intervalInHours,
IntervalStart: time.Date(intervalEndTime.Year(), intervalEndTime.Month(), intervalEndTime.Day(), 0, 0, 0, 0, intervalEndTime.Location()),
IntervalEndTime: intervalEndTime,
} }
stamps = append(stamps, stamp) stamps = append(stamps, stamp)
} }

View File

@ -52,26 +52,18 @@ func (db *storageUsageDB) Store(ctx context.Context, stamps []storageusage.Stamp
func (db *storageUsageDB) GetDaily(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (_ []storageusage.Stamp, err error) { func (db *storageUsageDB) GetDaily(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (_ []storageusage.Stamp, err error) {
defer mon.Task()(&ctx)(&err) defer mon.Task()(&ctx)(&err)
// the at_rest_total is in bytes*hours, so to find the total number // hour_interval = current row interval_end_time - previous row interval_end_time
// of hours used to get the at_rest_total, we find the hour difference,
// between the interval_end_time of a row and that of the previous row
// and divide the at_rest_total by the hour interval
// i.e. (at_rest_total/hour_difference), where the
// hour_difference = current row interval_end_time - previous row interval_end_time
// Rows with 0-hour difference are assumed to be 24 hours. // Rows with 0-hour difference are assumed to be 24 hours.
query := `SELECT satellite_id, query := `SELECT satellite_id,
( at_rest_total,
at_rest_total COALESCE(
/ (
COALESCE( CAST(strftime('%s', interval_end_time) AS NUMERIC)
( -
CAST(strftime('%s', interval_end_time) AS NUMERIC) CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
- ) / 3600,
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC) 24
) / 3600, ) AS hour_interval,
24
)
) AS at_rest_total,
timestamp timestamp
FROM storage_usage FROM storage_usage
WHERE satellite_id = ? WHERE satellite_id = ?
@ -87,18 +79,20 @@ func (db *storageUsageDB) GetDaily(ctx context.Context, satelliteID storj.NodeID
var stamps []storageusage.Stamp var stamps []storageusage.Stamp
for rows.Next() { for rows.Next() {
var satellite storj.NodeID var satellite storj.NodeID
var atRestTotal float64 var atRestTotal, intervalInHours float64
var timestamp time.Time var timestamp time.Time
err = rows.Scan(&satellite, &atRestTotal, &timestamp) err = rows.Scan(&satellite, &atRestTotal, &intervalInHours, &timestamp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
stamps = append(stamps, storageusage.Stamp{ stamps = append(stamps, storageusage.Stamp{
SatelliteID: satellite, SatelliteID: satellite,
AtRestTotal: atRestTotal, AtRestTotal: atRestTotal,
IntervalStart: timestamp, AtRestTotalBytes: atRestTotal / intervalInHours,
IntervalInHours: intervalInHours,
IntervalStart: timestamp,
}) })
} }
@ -110,28 +104,19 @@ func (db *storageUsageDB) GetDaily(ctx context.Context, satelliteID storj.NodeID
func (db *storageUsageDB) GetDailyTotal(ctx context.Context, from, to time.Time) (_ []storageusage.Stamp, err error) { func (db *storageUsageDB) GetDailyTotal(ctx context.Context, from, to time.Time) (_ []storageusage.Stamp, err error) {
defer mon.Task()(&ctx)(&err) defer mon.Task()(&ctx)(&err)
// the at_rest_total is in bytes*hours, so to find the total number // hour_interval = current row interval_end_time - previous row interval_end_time
// of hours used to get the at_rest_total, we find the hour difference,
// between the interval_end_time of a row and that of the previous row
// and divide the at_rest_total by the hour interval
// i.e. (at_rest_total/hour_difference), where the
// hour_difference = current row interval_end_time - previous row interval_end_time
// Rows with 0-hour difference are assumed to be 24 hours. // Rows with 0-hour difference are assumed to be 24 hours.
query := `SELECT SUM(usages.at_rest_total), usages.timestamp query := `SELECT SUM(usages.at_rest_total), SUM(usages.hour_interval), usages.timestamp
FROM ( FROM (
SELECT timestamp, SELECT at_rest_total, timestamp,
( COALESCE(
at_rest_total (
/ CAST(strftime('%s', interval_end_time) AS NUMERIC)
COALESCE( -
( CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
CAST(strftime('%s', interval_end_time) AS NUMERIC) ) / 3600,
- 24
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC) ) AS hour_interval
) / 3600,
24
)
) AS at_rest_total
FROM storage_usage FROM storage_usage
WHERE ? <= timestamp AND timestamp <= ? WHERE ? <= timestamp AND timestamp <= ?
) as usages ) as usages
@ -148,76 +133,76 @@ func (db *storageUsageDB) GetDailyTotal(ctx context.Context, from, to time.Time)
var stamps []storageusage.Stamp var stamps []storageusage.Stamp
for rows.Next() { for rows.Next() {
var atRestTotal float64 var atRestTotal, intervalInHours float64
var timestamp time.Time var timestamp time.Time
err = rows.Scan(&atRestTotal, &timestamp) err = rows.Scan(&atRestTotal, &intervalInHours, &timestamp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
stamps = append(stamps, storageusage.Stamp{ stamps = append(stamps, storageusage.Stamp{
AtRestTotal: atRestTotal, AtRestTotal: atRestTotal,
IntervalStart: timestamp, AtRestTotalBytes: atRestTotal / intervalInHours,
IntervalInHours: intervalInHours,
IntervalStart: timestamp,
}) })
} }
return stamps, rows.Err() return stamps, rows.Err()
} }
// Summary returns aggregated storage usage across all satellites. // Summary returns aggregated storage usage in Bytes*hour and average usage in bytes across all satellites.
func (db *storageUsageDB) Summary(ctx context.Context, from, to time.Time) (_ float64, err error) { func (db *storageUsageDB) Summary(ctx context.Context, from, to time.Time) (_, _ float64, err error) {
defer mon.Task()(&ctx, from, to)(&err) defer mon.Task()(&ctx, from, to)(&err)
var summary sql.NullFloat64 var summary, averageUsageInBytes sql.NullFloat64
query := `SELECT SUM(usages.at_rest_total) query := `SELECT SUM(usages.at_rest_total), AVG(usages.at_rest_total_bytes)
FROM ( FROM (
SELECT SELECT
( at_rest_total,
at_rest_total at_rest_total / (
/ COALESCE(
COALESCE( (
( CAST(strftime('%s', interval_end_time) AS NUMERIC)
CAST(strftime('%s', interval_end_time) AS NUMERIC) -
- CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC) ) / 3600,
) / 3600, 24
24 )
) ) AS at_rest_total_bytes
) AS at_rest_total
FROM storage_usage FROM storage_usage
WHERE ? <= timestamp AND timestamp <= ? WHERE ? <= timestamp AND timestamp <= ?
) as usages` ) as usages`
err = db.QueryRowContext(ctx, query, from.UTC(), to.UTC()).Scan(&summary) err = db.QueryRowContext(ctx, query, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
return summary.Float64, err return summary.Float64, averageUsageInBytes.Float64, err
} }
// SatelliteSummary returns aggregated storage usage for a particular satellite. // SatelliteSummary returns aggregated storage usage in Bytes*hour and average usage in bytes for a particular satellite.
func (db *storageUsageDB) SatelliteSummary(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (_ float64, err error) { func (db *storageUsageDB) SatelliteSummary(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (_, _ float64, err error) {
defer mon.Task()(&ctx, satelliteID, from, to)(&err) defer mon.Task()(&ctx, satelliteID, from, to)(&err)
var summary sql.NullFloat64 var summary, averageUsageInBytes sql.NullFloat64
query := `SELECT SUM(usages.at_rest_total) query := `SELECT SUM(usages.at_rest_total), AVG(usages.at_rest_total_bytes)
FROM ( FROM (
SELECT SELECT
( at_rest_total,
at_rest_total at_rest_total / (
/ COALESCE(
COALESCE( (
( CAST(strftime('%s', interval_end_time) AS NUMERIC)
CAST(strftime('%s', interval_end_time) AS NUMERIC) -
- CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC) ) / 3600,
) / 3600, 24
24 )
) ) AS at_rest_total_bytes
) AS at_rest_total
FROM storage_usage FROM storage_usage
WHERE satellite_id = ? WHERE satellite_id = ?
AND ? <= timestamp AND timestamp <= ? AND ? <= timestamp AND timestamp <= ?
) as usages` ) as usages`
err = db.QueryRowContext(ctx, query, satelliteID, from.UTC(), to.UTC()).Scan(&summary) err = db.QueryRowContext(ctx, query, satelliteID, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
return summary.Float64, err return summary.Float64, averageUsageInBytes.Float64, err
} }

View File

@ -23,16 +23,21 @@ type DB interface {
// for provided time range // for provided time range
GetDailyTotal(ctx context.Context, from, to time.Time) ([]Stamp, error) GetDailyTotal(ctx context.Context, from, to time.Time) ([]Stamp, error)
// Summary returns aggregated storage usage across all satellites. // Summary returns aggregated storage usage across all satellites.
Summary(ctx context.Context, from, to time.Time) (float64, error) Summary(ctx context.Context, from, to time.Time) (float64, float64, error)
// SatelliteSummary returns aggregated storage usage for a particular satellite. // SatelliteSummary returns aggregated storage usage for a particular satellite.
SatelliteSummary(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (float64, error) SatelliteSummary(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (float64, float64, error)
} }
// Stamp is storage usage stamp for satellite from interval start till next interval. // Stamp is storage usage stamp for satellite from interval start till next interval.
type Stamp struct { type Stamp struct {
SatelliteID storj.NodeID `json:"-"` SatelliteID storj.NodeID `json:"-"`
// AtRestTotal is the disk space used from IntervalStart to IntervalEndTime in Bytes*day // AtRestTotal is the bytes*hour disk space used at the IntervalEndTime.
AtRestTotal float64 `json:"atRestTotal"` AtRestTotal float64 `json:"atRestTotal"`
// AtRestTotalBytes is the AtRestTotal divided by the IntervalInHours.
AtRestTotalBytes float64 `json:"atRestTotalBytes"`
// IntervalInHours is hour difference between interval_end_time
// of this Stamp and that of the preceding Stamp
IntervalInHours float64 `json:"intervalInHours"`
// IntervalStart represents one tally day // IntervalStart represents one tally day
// TODO: rename to timestamp to match DB // TODO: rename to timestamp to match DB
IntervalStart time.Time `json:"intervalStart"` IntervalStart time.Time `json:"intervalStart"`

View File

@ -36,10 +36,11 @@ func TestStorageUsage(t *testing.T) {
stamps := storagenodedbtest.MakeStorageUsageStamps(satellites, days, now) stamps := storagenodedbtest.MakeStorageUsageStamps(satellites, days, now)
var totalSummary float64 var totalSummary, averageUsage float64
expectedDailyStamps := make(map[storj.NodeID]map[time.Time]storageusage.Stamp) expectedDailyStamps := make(map[storj.NodeID]map[time.Time]storageusage.Stamp)
expectedDailyStampsTotals := make(map[time.Time]float64) expectedDailyStampsTotals := make(map[time.Time]float64)
summary := make(map[storj.NodeID]float64) summaryBySatellite := make(map[storj.NodeID]float64)
averageBySatellite := make(map[storj.NodeID]float64)
for _, stamp := range stamps { for _, stamp := range stamps {
if expectedDailyStamps[stamp.SatelliteID] == nil { if expectedDailyStamps[stamp.SatelliteID] == nil {
@ -48,27 +49,29 @@ func TestStorageUsage(t *testing.T) {
expectedDailyStamps[stamp.SatelliteID][stamp.IntervalStart.UTC()] = stamp expectedDailyStamps[stamp.SatelliteID][stamp.IntervalStart.UTC()] = stamp
} }
totalUsageBytes := float64(0)
totalStamps := float64(0)
for _, satellite := range satellites { for _, satellite := range satellites {
satelliteUsageBytes := float64(0)
for _, stamp := range expectedDailyStamps[satellite] { for _, stamp := range expectedDailyStamps[satellite] {
intervalStart := stamp.IntervalStart.UTC() intervalStart := stamp.IntervalStart.UTC()
prevTimestamp := intervalStart.AddDate(0, 0, -1)
atRestTotal := stamp.AtRestTotal / 24 expectedDailyStampsTotals[intervalStart] += stamp.AtRestTotal
if prevStamp, ok := expectedDailyStamps[satellite][prevTimestamp]; ok {
diff := stamp.IntervalEndTime.UTC().Sub(prevStamp.IntervalEndTime.UTC()).Hours() summaryBySatellite[satellite] += stamp.AtRestTotal
atRestTotal = stamp.AtRestTotal / diff totalSummary += stamp.AtRestTotal
}
expectedDailyStamps[satellite][intervalStart] = storageusage.Stamp{ satelliteUsageBytes += stamp.AtRestTotalBytes
SatelliteID: satellite, totalUsageBytes += stamp.AtRestTotalBytes
AtRestTotal: atRestTotal,
IntervalStart: intervalStart, totalStamps++
IntervalEndTime: stamp.IntervalEndTime,
}
expectedDailyStampsTotals[intervalStart] += atRestTotal
summary[satellite] += atRestTotal
totalSummary += atRestTotal
} }
averageBySatellite[satellite] = satelliteUsageBytes / float64(len(expectedDailyStamps[satellite]))
} }
averageUsage = totalUsageBytes / totalStamps
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) { storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
storageUsageDB := db.StorageUsage() storageUsageDB := db.StorageUsage()
@ -85,6 +88,8 @@ func TestStorageUsage(t *testing.T) {
for _, stamp := range res { for _, stamp := range res {
assert.Equal(t, satelliteID, stamp.SatelliteID) assert.Equal(t, satelliteID, stamp.SatelliteID)
assert.Equal(t, expectedDailyStamps[satelliteID][stamp.IntervalStart].AtRestTotal, stamp.AtRestTotal) assert.Equal(t, expectedDailyStamps[satelliteID][stamp.IntervalStart].AtRestTotal, stamp.AtRestTotal)
assert.Equal(t, expectedDailyStamps[satelliteID][stamp.IntervalStart].AtRestTotalBytes, stamp.AtRestTotalBytes)
assert.Equal(t, expectedDailyStamps[satelliteID][stamp.IntervalStart].IntervalInHours, stamp.IntervalInHours)
} }
}) })
@ -103,22 +108,24 @@ func TestStorageUsage(t *testing.T) {
}) })
t.Run("summary satellite", func(t *testing.T) { t.Run("summary satellite", func(t *testing.T) {
summ, err := storageUsageDB.SatelliteSummary(ctx, satelliteID, time.Time{}, now) summ, averageUsageInBytes, err := storageUsageDB.SatelliteSummary(ctx, satelliteID, time.Time{}, now)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, roundFloat(summary[satelliteID]), roundFloat(summ)) assert.Equal(t, roundFloat(summaryBySatellite[satelliteID]), roundFloat(summ))
assert.Equal(t, roundFloat(averageBySatellite[satelliteID]), roundFloat(averageUsageInBytes))
}) })
t.Run("summary", func(t *testing.T) { t.Run("summary", func(t *testing.T) {
summ, err := storageUsageDB.Summary(ctx, time.Time{}, now) summ, averageUsageInBytes, err := storageUsageDB.Summary(ctx, time.Time{}, now)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, roundFloat(totalSummary), roundFloat(summ)) assert.Equal(t, roundFloat(totalSummary), roundFloat(summ))
assert.Equal(t, roundFloat(averageUsage), roundFloat(averageUsageInBytes))
}) })
}) })
} }
func TestEmptyStorageUsage(t *testing.T) { func TestEmptyStorageUsage(t *testing.T) {
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) { storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
var emptySummary float64 var emptySummary, zeroHourInterval float64
now := time.Now() now := time.Now()
storageUsageDB := db.StorageUsage() storageUsageDB := db.StorageUsage()
@ -136,15 +143,17 @@ func TestEmptyStorageUsage(t *testing.T) {
}) })
t.Run("summary satellite", func(t *testing.T) { t.Run("summary satellite", func(t *testing.T) {
summ, err := storageUsageDB.SatelliteSummary(ctx, storj.NodeID{}, time.Time{}, now) summ, hourInterval, err := storageUsageDB.SatelliteSummary(ctx, storj.NodeID{}, time.Time{}, now)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, emptySummary, summ) assert.Equal(t, emptySummary, summ)
assert.Equal(t, zeroHourInterval, hourInterval)
}) })
t.Run("summary", func(t *testing.T) { t.Run("summary", func(t *testing.T) {
summ, err := storageUsageDB.Summary(ctx, time.Time{}, now) summ, hourInterval, err := storageUsageDB.Summary(ctx, time.Time{}, now)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, emptySummary, summ) assert.Equal(t, emptySummary, summ)
assert.Equal(t, zeroHourInterval, hourInterval)
}) })
}) })
} }

View File

@ -52,8 +52,9 @@ export class StorageClient extends APIClient {
const usage = data.stamps || []; const usage = data.stamps || [];
return new DiskSpaceUsage( return new DiskSpaceUsage(
usage.map(stamp => new Stamp(stamp.atRestTotal, new Date(stamp.intervalStart))), usage.map(stamp => new Stamp(stamp.atRestTotal, stamp.atRestTotalBytes, new Date(stamp.intervalStart))),
data.summary, data.summary,
data.summaryBytes,
); );
} }

View File

@ -31,10 +31,12 @@ import BaseChart from '@/app/components/common/BaseChart.vue';
*/ */
class StampTooltip { class StampTooltip {
public atRestTotal: string; public atRestTotal: string;
public atRestTotalBytes: string;
public date: string; public date: string;
public constructor(stamp: Stamp) { public constructor(stamp: Stamp) {
this.atRestTotal = Size.toBase10String(stamp.atRestTotal); this.atRestTotal = Size.toBase10String(stamp.atRestTotal);
this.atRestTotalBytes = Size.toBase10String(stamp.atRestTotalBytes);
this.date = stamp.intervalStart.toUTCString().slice(0, 16); this.date = stamp.intervalStart.toUTCString().slice(0, 16);
} }
} }
@ -53,7 +55,7 @@ export default class DiskSpaceChart extends BaseChart {
return 'Bytes'; return 'Bytes';
} }
return ChartUtils.getChartDataDimension(this.allStamps.map((elem) => elem.atRestTotal)); return ChartUtils.getChartDataDimension(this.allStamps.map((elem) => elem.atRestTotalBytes));
} }
public get chartData(): ChartData { public get chartData(): ChartData {
@ -64,7 +66,7 @@ export default class DiskSpaceChart extends BaseChart {
const chartBorderWidth = 1; const chartBorderWidth = 1;
if (this.allStamps.length) { if (this.allStamps.length) {
data = ChartUtils.normalizeChartData(this.allStamps.map(elem => elem.atRestTotal)); data = ChartUtils.normalizeChartData(this.allStamps.map(elem => elem.atRestTotalBytes));
} }
return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data); return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data);
@ -86,7 +88,7 @@ export default class DiskSpaceChart extends BaseChart {
const dataPoint = new StampTooltip(this.allStamps[dataIndex]); const dataPoint = new StampTooltip(this.allStamps[dataIndex]);
return `<div class='tooltip-body'> return `<div class='tooltip-body'>
<p class='tooltip-body__data'><b>${dataPoint.atRestTotal}</b></p> <p class='tooltip-body__data'><b>${dataPoint.atRestTotalBytes}</b></p>
<p class='tooltip-body__footer'>${dataPoint.date}</p> <p class='tooltip-body__footer'>${dataPoint.date}</p>
</div>`; </div>`;
} }

View File

@ -53,9 +53,9 @@
<section class="bandwidth__chart-area"> <section class="bandwidth__chart-area">
<section class="chart-container"> <section class="chart-container">
<div class="chart-container__title-area disk-space-title"> <div class="chart-container__title-area disk-space-title">
<p class="chart-container__title-area__title">Disk Space Used This Month</p> <p class="chart-container__title-area__title">Average Disk Space Used This Month</p>
</div> </div>
<p class="chart-container__amount disk-space-amount"><b>{{ diskSpaceUsageSummary | bytesToBase10String }}*d</b></p> <p class="chart-container__amount disk-space-amount"><b>{{ diskSpaceUsageSummary | bytesToBase10String }}</b></p>
<div ref="diskSpaceChart" class="chart-container__chart" onresize="recalculateChartDimensions()"> <div ref="diskSpaceChart" class="chart-container__chart" onresize="recalculateChartDimensions()">
<disk-space-chart :height="diskSpaceChartHeight" :width="diskSpaceChartWidth" /> <disk-space-chart :height="diskSpaceChartHeight" :width="diskSpaceChartWidth" />
</div> </div>
@ -110,7 +110,7 @@ export default class BandwidthPage extends Vue {
} }
public get diskSpaceUsageSummary(): number { public get diskSpaceUsageSummary(): number {
return this.$store.state.storage.usage.diskSpaceSummary; return this.$store.state.storage.usage.diskSpaceSummaryBytes;
} }
/** /**

View File

@ -6,10 +6,12 @@
*/ */
export class Stamp { export class Stamp {
public atRestTotal: number; public atRestTotal: number;
public atRestTotalBytes: number;
public intervalStart: Date; public intervalStart: Date;
public constructor(atRestTotal = 0, intervalStart: Date = new Date()) { public constructor(atRestTotal = 0, atRestTotalBytes = 0, intervalStart: Date = new Date()) {
this.atRestTotal = atRestTotal; this.atRestTotal = atRestTotal;
this.atRestTotalBytes = atRestTotalBytes;
this.intervalStart = intervalStart; this.intervalStart = intervalStart;
} }
@ -24,7 +26,7 @@ export class Stamp {
now.setUTCDate(date); now.setUTCDate(date);
now.setUTCHours(0, 0, 0, 0); now.setUTCHours(0, 0, 0, 0);
return new Stamp(0, now); return new Stamp(0, 0, now);
} }
} }
@ -49,5 +51,6 @@ export class DiskSpaceUsage {
public constructor( public constructor(
public diskSpaceDaily: Stamp[] = [], public diskSpaceDaily: Stamp[] = [],
public diskSpaceSummary: number = 0, public diskSpaceSummary: number = 0,
public diskSpaceSummaryBytes: number = 0,
) {} ) {}
} }

View File

@ -26,9 +26,9 @@ exports[`BandwidthPage renders correctly 1`] = `
<section class="bandwidth__chart-area"> <section class="bandwidth__chart-area">
<section class="chart-container"> <section class="chart-container">
<div class="chart-container__title-area disk-space-title"> <div class="chart-container__title-area disk-space-title">
<p class="chart-container__title-area__title">Disk Space Used This Month</p> <p class="chart-container__title-area__title">Average Disk Space Used This Month</p>
</div> </div>
<p class="chart-container__amount disk-space-amount"><b>0B*d</b></p> <p class="chart-container__amount disk-space-amount"><b>0B</b></p>
<div onresize="recalculateChartDimensions()" class="chart-container__chart"> <div onresize="recalculateChartDimensions()" class="chart-container__chart">
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub> <disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
</div> </div>
@ -66,9 +66,9 @@ exports[`BandwidthPage renders correctly with egress chart 1`] = `
<section class="bandwidth__chart-area"> <section class="bandwidth__chart-area">
<section class="chart-container"> <section class="chart-container">
<div class="chart-container__title-area disk-space-title"> <div class="chart-container__title-area disk-space-title">
<p class="chart-container__title-area__title">Disk Space Used This Month</p> <p class="chart-container__title-area__title">Average Disk Space Used This Month</p>
</div> </div>
<p class="chart-container__amount disk-space-amount"><b>0B*d</b></p> <p class="chart-container__amount disk-space-amount"><b>0B</b></p>
<div onresize="recalculateChartDimensions()" class="chart-container__chart"> <div onresize="recalculateChartDimensions()" class="chart-container__chart">
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub> <disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
</div> </div>
@ -106,9 +106,9 @@ exports[`BandwidthPage renders correctly with ingress chart 1`] = `
<section class="bandwidth__chart-area"> <section class="bandwidth__chart-area">
<section class="chart-container"> <section class="chart-container">
<div class="chart-container__title-area disk-space-title"> <div class="chart-container__title-area disk-space-title">
<p class="chart-container__title-area__title">Disk Space Used This Month</p> <p class="chart-container__title-area__title">Average Disk Space Used This Month</p>
</div> </div>
<p class="chart-container__amount disk-space-amount"><b>0B*d</b></p> <p class="chart-container__amount disk-space-amount"><b>0B</b></p>
<div onresize="recalculateChartDimensions()" class="chart-container__chart"> <div onresize="recalculateChartDimensions()" class="chart-container__chart">
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub> <disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
</div> </div>

View File

@ -31,10 +31,12 @@ import BaseChart from '@/app/components/BaseChart.vue';
*/ */
class StampTooltip { class StampTooltip {
public atRestTotal: string; public atRestTotal: string;
public atRestTotalBytes: string;
public date: string; public date: string;
public constructor(stamp: Stamp) { public constructor(stamp: Stamp) {
this.atRestTotal = Size.toBase10String(stamp.atRestTotal); this.atRestTotal = Size.toBase10String(stamp.atRestTotal);
this.atRestTotalBytes = Size.toBase10String(stamp.atRestTotalBytes);
this.date = stamp.intervalStart.toUTCString().slice(0, 16); this.date = stamp.intervalStart.toUTCString().slice(0, 16);
} }
} }
@ -58,7 +60,7 @@ export default class DiskSpaceChart extends BaseChart {
} }
return ChartUtils.getChartDataDimension(this.allStamps.map((elem) => { return ChartUtils.getChartDataDimension(this.allStamps.map((elem) => {
return elem.atRestTotal; return elem.atRestTotalBytes;
})); }));
} }
@ -70,7 +72,7 @@ export default class DiskSpaceChart extends BaseChart {
const chartBorderWidth = 1; const chartBorderWidth = 1;
if (this.allStamps.length) { if (this.allStamps.length) {
data = ChartUtils.normalizeChartData(this.allStamps.map(elem => elem.atRestTotal)); data = ChartUtils.normalizeChartData(this.allStamps.map(elem => elem.atRestTotalBytes));
} }
return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data); return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data);
@ -93,7 +95,7 @@ export default class DiskSpaceChart extends BaseChart {
const dataPoint = new StampTooltip(this.allStamps[dataIndex]); const dataPoint = new StampTooltip(this.allStamps[dataIndex]);
return `<div class='tooltip-body'> return `<div class='tooltip-body'>
<p class='tooltip-body__data'><b>${dataPoint.atRestTotal}</b></p> <p class='tooltip-body__data'><b>${dataPoint.atRestTotalBytes}</b></p>
<p class='tooltip-body__footer'>${dataPoint.date}</p> <p class='tooltip-body__footer'>${dataPoint.date}</p>
</div>`; </div>`;
} }

View File

@ -112,9 +112,9 @@
<section class="info-area__chart-area"> <section class="info-area__chart-area">
<section class="chart-container"> <section class="chart-container">
<div class="chart-container__title-area disk-space-title"> <div class="chart-container__title-area disk-space-title">
<p class="chart-container__title-area__title">Disk Space Used This Month</p> <p class="chart-container__title-area__title">Average Disk Space Used This Month</p>
</div> </div>
<p class="chart-container__amount disk-space-amount"><b>{{ storageSummary }}*d</b></p> <p class="chart-container__amount disk-space-amount"><b>{{ averageUsageBytes }}</b></p>
<div ref="diskSpaceChart" class="chart-container__chart" onresize="recalculateChartDimensions()"> <div ref="diskSpaceChart" class="chart-container__chart" onresize="recalculateChartDimensions()">
<DiskSpaceChart :height="diskSpaceChartHeight" :width="diskSpaceChartWidth" :is-dark-mode="isDarkMode" /> <DiskSpaceChart :height="diskSpaceChartHeight" :width="diskSpaceChartWidth" :is-dark-mode="isDarkMode" />
</div> </div>
@ -330,8 +330,8 @@ export default class SNOContentFilling extends Vue {
* storageSummary - amount of monthly disk space used from store. * storageSummary - amount of monthly disk space used from store.
* @return string - formatted amount of monthly disk space used * @return string - formatted amount of monthly disk space used
*/ */
public get storageSummary(): string { public get averageUsageBytes(): string {
return Size.toBase10String(this.$store.state.node.storageSummary); return Size.toBase10String(this.$store.state.node.averageUsageBytes);
} }
/** /**

View File

@ -118,6 +118,7 @@ export function newNodeModule(service: StorageNodeService): StoreModule<StorageN
state.egressSummary = satelliteInfo.egressSummary; state.egressSummary = satelliteInfo.egressSummary;
state.ingressSummary = satelliteInfo.ingressSummary; state.ingressSummary = satelliteInfo.ingressSummary;
state.storageSummary = satelliteInfo.storageSummary; state.storageSummary = satelliteInfo.storageSummary;
state.averageUsageBytes = satelliteInfo.averageUsageBytes;
}, },
}, },
actions: { actions: {

View File

@ -27,6 +27,7 @@ export class StorageNodeState {
public ingressChartData: IngressUsed[] = []; public ingressChartData: IngressUsed[] = [];
public storageChartData: Stamp[] = []; public storageChartData: Stamp[] = [];
public storageSummary = 0; public storageSummary = 0;
public averageUsageBytes = 0;
public bandwidthSummary = 0; public bandwidthSummary = 0;
public egressSummary = 0; public egressSummary = 0;
public ingressSummary = 0; public ingressSummary = 0;

View File

@ -79,6 +79,7 @@ export class StorageNodeApi {
satelliteByDayInfo.egressDaily, satelliteByDayInfo.egressDaily,
satelliteByDayInfo.ingressDaily, satelliteByDayInfo.ingressDaily,
data.storageSummary, data.storageSummary,
data.averageUsageBytes,
data.bandwidthSummary, data.bandwidthSummary,
data.egressSummary, data.egressSummary,
data.ingressSummary, data.ingressSummary,
@ -119,6 +120,7 @@ export class StorageNodeApi {
satelliteByDayInfo.egressDaily, satelliteByDayInfo.egressDaily,
satelliteByDayInfo.ingressDaily, satelliteByDayInfo.ingressDaily,
data.storageSummary, data.storageSummary,
data.averageUsageBytes,
data.bandwidthSummary, data.bandwidthSummary,
data.egressSummary, data.egressSummary,
data.ingressSummary, data.ingressSummary,

View File

@ -106,6 +106,7 @@ export class Satellite {
public egressDaily: EgressUsed[] = [], public egressDaily: EgressUsed[] = [],
public ingressDaily: IngressUsed[] = [], public ingressDaily: IngressUsed[] = [],
public storageSummary: number = 0, public storageSummary: number = 0,
public averageUsageBytes: number = 0,
public bandwidthSummary: number = 0, public bandwidthSummary: number = 0,
public egressSummary: number = 0, public egressSummary: number = 0,
public ingressSummary: number = 0, public ingressSummary: number = 0,
@ -119,10 +120,12 @@ export class Satellite {
*/ */
export class Stamp { export class Stamp {
public atRestTotal: number; public atRestTotal: number;
public atRestTotalBytes: number;
public intervalStart: Date; public intervalStart: Date;
public constructor(atRestTotal = 0, intervalStart: Date = new Date()) { public constructor(atRestTotal = 0, atRestTotalBytes = 0, intervalStart: Date = new Date()) {
this.atRestTotal = atRestTotal; this.atRestTotal = atRestTotal;
this.atRestTotalBytes = atRestTotalBytes;
this.intervalStart = intervalStart; this.intervalStart = intervalStart;
} }
@ -136,7 +139,7 @@ export class Stamp {
now.setUTCDate(date); now.setUTCDate(date);
now.setUTCHours(0, 0, 0, 0); now.setUTCHours(0, 0, 0, 0);
return new Stamp(0, now); return new Stamp(0, 0, now);
} }
} }
@ -282,6 +285,7 @@ export class Satellites {
public egressDaily: EgressUsed[] = [], public egressDaily: EgressUsed[] = [],
public ingressDaily: IngressUsed[] = [], public ingressDaily: IngressUsed[] = [],
public storageSummary: number = 0, public storageSummary: number = 0,
public averageUsageBytes: number = 0,
public bandwidthSummary: number = 0, public bandwidthSummary: number = 0,
public egressSummary: number = 0, public egressSummary: number = 0,
public ingressSummary: number = 0, public ingressSummary: number = 0,
@ -372,7 +376,7 @@ export class SatelliteByDayInfo {
const bandwidthDailyJson = data.bandwidthDaily || []; const bandwidthDailyJson = data.bandwidthDaily || [];
this.storageDaily = storageDailyJson.map((stamp: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any this.storageDaily = storageDailyJson.map((stamp: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
return new Stamp(stamp.atRestTotal, new Date(stamp.intervalStart)); return new Stamp(stamp.atRestTotal, stamp.atRestTotalBytes, new Date(stamp.intervalStart));
}); });
this.bandwidthDaily = bandwidthDailyJson.map((bandwidth: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any this.bandwidthDaily = bandwidthDailyJson.map((bandwidth: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any

View File

@ -51,6 +51,7 @@ describe('EstimationPeriodDropdown', (): void => {
[], [],
[], [],
111, 111,
11,
222, 222,
50, 50,
70, 70,

View File

@ -68,7 +68,7 @@ describe('PayoutHistoryPeriodDropdown', (): void => {
localVue, localVue,
}); });
const satelliteInfo = new Satellites([], [], [], [], 0, 0, 0, 0, new Date(2020, 1)); const satelliteInfo = new Satellites([], [], [], [], 0, 0, 0, 0, 0, new Date(2020, 1));
await store.commit(NODE_MUTATIONS.SELECT_ALL_SATELLITES, satelliteInfo); await store.commit(NODE_MUTATIONS.SELECT_ALL_SATELLITES, satelliteInfo);

View File

@ -56,6 +56,7 @@ describe('TotalHeldArea', (): void => {
[], [],
[], [],
111, 111,
11,
222, 222,
50, 50,
70, 70,

View File

@ -78,6 +78,7 @@ describe('mutations', () => {
[], [],
[], [],
111, 111,
11,
222, 222,
50, 50,
70, 70,
@ -140,6 +141,7 @@ describe('mutations', () => {
new IngressUsed(new Ingress(), new Date()), new IngressUsed(new Ingress(), new Date()),
], ],
111, 111,
11,
222, 222,
50, 50,
70, 70,
@ -244,6 +246,7 @@ describe('actions', () => {
new IngressUsed(new Ingress(), new Date()), new IngressUsed(new Ingress(), new Date()),
], ],
1111, 1111,
111,
2221, 2221,
501, 501,
701, 701,
@ -313,6 +316,7 @@ describe('getters', () => {
[], [],
[], [],
111, 111,
11,
222, 222,
50, 50,
70, 70,