Created
June 9, 2018 20:17
-
-
Save Nearhan/63927a790afdf4ff46351990cc2220d3 to your computer and use it in GitHub Desktop.
project struct
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package project | |
import ( | |
"encoding/json" | |
"time" | |
"github.com/satori/go.uuid" | |
"gitlab.qntfy.com/qcr/drago/core" | |
"gitlab.qntfy.com/qcr/drago/networks" | |
) | |
// Project struct used by QCR api version 2 | |
type Project struct { | |
ID uuid.UUID `json:"id"` | |
Start UnixTime `json:"startTimestamp"` | |
End *UnixTime `json:"endTimestamp"` | |
Definitions []Definition `json:"definitions"` | |
} | |
// Definition what a definition is | |
type Definition struct { | |
ID uuid.UUID `json:"id"` | |
Content []Field `json:"content"` | |
Filter []Field `json:"filter"` | |
Exclude []Field `json:"exclude"` | |
} | |
// Field has a category and a list of values | |
type Field struct { | |
Category string `json:"category"` | |
Values []interface{} `json:"values"` | |
} | |
// ToRuleAble returns the a category type that knows how to extract rules | |
func (f *Field) ToRuleAble() (RuleAble, error) { | |
switch f.Category { | |
case "keywords": | |
return NewKeywordCategory(f.Values) | |
case "hashtags": | |
return NewHashtagCategory(f.Values) | |
case "geo": | |
return NewGeoCategory(f.Values) | |
case "url": | |
return NewURLCategory(f.Values) | |
default: | |
return nil, ErrNotSupportedContentCategory | |
} | |
} | |
// UnixTime holds TimeStamp as unix time stamp | |
type UnixTime struct { | |
time.Time | |
} | |
// UnmarshalJSON implements interface | |
func (t *UnixTime) UnmarshalJSON(data []byte) error { | |
var i int64 | |
if err := json.Unmarshal(data, &i); err != nil { | |
return err | |
} | |
*t = UnixTime{time.Unix(i, 0)} | |
return nil | |
} | |
// MarshalJSON implements interface | |
func (t *UnixTime) MarshalJSON() ([]byte, error) { | |
i := t.Unix() | |
return json.Marshal(i) | |
} | |
// RuleAble used to turn supported categories into rules | |
type RuleAble interface { | |
ToRules() (core.ProtoableRules, error) | |
} | |
// ConvertToProjectRequest takes a project and turns it into a core.ProjectRequest | |
func ConvertToProjectRequest(p *Project) (core.ProjectRequest, error) { | |
var proj core.ProjectRequest | |
var rules core.ProtoableRules | |
for _, def := range p.Definitions { | |
for _, criteria := range def.Content { | |
t, err := criteria.ToRuleAble() | |
if err != nil { | |
return proj, err | |
} | |
rs, err := t.ToRules() | |
if err != nil { | |
return proj, err | |
} | |
rules = append(rules, rs...) | |
} | |
} | |
var dr core.DataRequest | |
if p.End == nil { | |
dr = core.NewEndlessDataRequest(p.ID, p.Start.UTC(), rules...) | |
} else { | |
dr = core.NewDataRequest(p.ID, p.Start.UTC(), p.End.UTC(), rules...) | |
} | |
raw, err := json.Marshal(p) | |
if err != nil { | |
return proj, err | |
} | |
return core.ProjectRequest{dr, raw}, nil | |
} | |
// ConvertFromProjectRequest takes a core.ProjectRequest and creates a Project via json unmarshal | |
func ConvertFromProjectRequest(pr core.ProjectRequest) (*Project, error) { | |
var p Project | |
err := json.Unmarshal(pr.Project, &p) | |
return &p, err | |
} | |
// KeywordCategory keyword specific category | |
type KeywordCategory struct { | |
keywords []string | |
} | |
// ToRules knows how to turn keywords into core.ProtoableRules | |
func (k KeywordCategory) ToRules() (core.ProtoableRules, error) { | |
var rules core.ProtoableRules | |
for _, w := range k.keywords { | |
for _, n := range networks.List() { | |
r, err := core.NewTermRule(n, w) | |
if err != nil { | |
return rules, err | |
} | |
rules = append(rules, &r) | |
} | |
} | |
return checkRuleDuplication("keywords", rules) | |
} | |
// NewKeywordCategory makes a new KeywordCategory, converts inputs | |
func NewKeywordCategory(words []interface{}) (KeywordCategory, error) { | |
keywords := []string{} | |
for _, w := range words { | |
var s string | |
var ok bool | |
if s, ok = w.(string); !ok { | |
return KeywordCategory{}, NewFieldTypeError("keyword", "string") | |
} | |
keywords = append(keywords, s) | |
} | |
return KeywordCategory{keywords}, nil | |
} | |
// GeoCategory geo specific category | |
type GeoCategory struct { | |
geos [][]float64 | |
} | |
// ToRules knows how to turn float64 into core.ProtoableRules | |
func (g GeoCategory) ToRules() (core.ProtoableRules, error) { | |
var rules core.ProtoableRules | |
for _, geo := range g.geos { | |
for _, n := range networks.List() { | |
r, err := core.NewGeoRule(n, geo) | |
if err != nil { | |
return rules, err | |
} | |
rules = append(rules, &r) | |
} | |
} | |
return checkRuleDuplication("geos", rules) | |
} | |
// NewGeoCategory makes a new GeoCategory, converts inputs to []float64 | |
func NewGeoCategory(arrypoints []interface{}) (GeoCategory, error) { | |
var geos [][]float64 | |
var points []interface{} | |
var p float64 | |
var ok bool | |
//extract inner array | |
for _, ps := range arrypoints { | |
if points, ok = ps.([]interface{}); !ok { | |
return GeoCategory{}, NewFieldTypeError("[]geo", "[]float64") | |
} | |
geo := []float64{} | |
for _, point := range points { | |
if p, ok = point.(float64); !ok { | |
return GeoCategory{}, NewFieldTypeError("geo", "float64") | |
} | |
geo = append(geo, p) | |
} | |
geos = append(geos, geo) | |
} | |
return GeoCategory{geos}, nil | |
} | |
// URLCategory url specific category | |
type URLCategory struct { | |
urls []string | |
} | |
// ToRules knows how to turn urls into core.ProtoableRules | |
func (u URLCategory) ToRules() (core.ProtoableRules, error) { | |
var rules core.ProtoableRules | |
for _, u := range u.urls { | |
for _, n := range networks.List() { | |
r, err := core.NewURLRule(n, u) | |
if err != nil { | |
return rules, err | |
} | |
rules = append(rules, &r) | |
} | |
} | |
return checkRuleDuplication("url", rules) | |
} | |
// NewURLCategory makes a new UrlCategory, converts inputs | |
func NewURLCategory(urls []interface{}) (URLCategory, error) { | |
urlz := []string{} | |
for _, url := range urls { | |
var u string | |
var ok bool | |
if u, ok = url.(string); !ok { | |
return URLCategory{}, NewFieldTypeError("urls", "string") | |
} | |
urlz = append(urlz, u) | |
} | |
return URLCategory{urlz}, nil | |
} | |
// HashtagCategory hastag specific category | |
type HashtagCategory struct { | |
tags []string | |
} | |
// ToRules knows how to turn hashtags into core.ProtoableRules | |
func (h HashtagCategory) ToRules() (core.ProtoableRules, error) { | |
var rules core.ProtoableRules | |
for _, ht := range h.tags { | |
for _, n := range networks.List() { | |
r, err := core.NewTermRule(n, ht) | |
if err != nil { | |
return rules, err | |
} | |
rules = append(rules, &r) | |
} | |
} | |
return checkRuleDuplication("hashtag", rules) | |
} | |
// NewHashtagCategory makes a new HastagCategory, converts inputs | |
func NewHashtagCategory(tags []interface{}) (HashtagCategory, error) { | |
hashtags := []string{} | |
for _, tag := range tags { | |
var t string | |
var ok bool | |
if t, ok = tag.(string); !ok { | |
return HashtagCategory{}, NewFieldTypeError("hashtags", "string") | |
} | |
hashtags = append(hashtags, t) | |
} | |
return HashtagCategory{hashtags}, nil | |
} | |
func checkRuleDuplication(category string, rules core.ProtoableRules) (core.ProtoableRules, error) { | |
if len(rules) != len(rules.IDToRuleMap()) { | |
return rules, NewFieldDuplicateValueError(category) | |
} | |
return rules, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment