├── heroku.yml ├── .gitignore ├── docs ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── YTThumbnail.png └── screenshot001.png ├── image0.jpg ├── image1.jpg ├── image2.jpg ├── image3.jpg ├── image4.jpg ├── image5.jpg ├── redis ├── config.go └── redis.go ├── public ├── favicon.ico ├── css │ └── app.c9128dab.css ├── index.html └── js │ ├── app.d61e56cf.js │ └── app.d61e56cf.js.map ├── api ├── config.go ├── server.go └── router.go ├── images └── app_preview_image.png ├── .env.example ├── config ├── import.go ├── redis.go ├── api.go └── config.go ├── go.mod ├── controller ├── company.go ├── redis.go └── controller.go ├── docker-compose.yaml ├── internal └── waiting.go ├── main.go ├── Dockerfile ├── LICENSE ├── app.json ├── marketplace.json ├── README.md ├── seed.json └── go.sum /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env.local 3 | .idea 4 | basic-redis-leaderboard-demo-go 5 | -------------------------------------------------------------------------------- /docs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/1.png -------------------------------------------------------------------------------- /docs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/2.png -------------------------------------------------------------------------------- /docs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/3.png -------------------------------------------------------------------------------- /docs/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/4.png -------------------------------------------------------------------------------- /image0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image0.jpg -------------------------------------------------------------------------------- /image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image1.jpg -------------------------------------------------------------------------------- /image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image2.jpg -------------------------------------------------------------------------------- /image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image3.jpg -------------------------------------------------------------------------------- /image4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image4.jpg -------------------------------------------------------------------------------- /image5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image5.jpg -------------------------------------------------------------------------------- /redis/config.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | type Config interface { 4 | Addr() string 5 | Password() string 6 | } 7 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/public/favicon.ico -------------------------------------------------------------------------------- /docs/YTThumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/YTThumbnail.png -------------------------------------------------------------------------------- /docs/screenshot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/docs/screenshot001.png -------------------------------------------------------------------------------- /api/config.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type Config interface { 4 | Addr() string 5 | PublicPath() string 6 | TLSDisabled() bool 7 | } 8 | -------------------------------------------------------------------------------- /images/app_preview_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/images/app_preview_image.png -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | API_HOST= 2 | API_PORT=8080 3 | API_PUBLIC_PATH=/public 4 | IMPORT_PATH=/seed.json 5 | REDIS_HOST=leaderboard-redis 6 | REDIS_PORT=6379 7 | REDIS_PASSWORD= 8 | -------------------------------------------------------------------------------- /config/import.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | const ( 4 | defaultImportPath = "./seed.json" 5 | 6 | envImportPath = "IMPORT_PATH" 7 | ) 8 | 9 | type Import struct { 10 | path string 11 | } 12 | 13 | func (i Import) Path() string { 14 | return i.path 15 | } 16 | -------------------------------------------------------------------------------- /public/css/app.c9128dab.css: -------------------------------------------------------------------------------- 1 | [data-v-6d7466c0] .v-data-table>.v-data-table__wrapper>table>thead>tr>th{color:#444}[data-v-6d7466c0] .v-data-table{color:#212529;font-weight:500}#app{font-family:Noto Sans JP,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;margin-top:60px;background:#f4f4f4}pre{background:#f6f8fa;padding:3px 5px;display:inline} -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/redis-developer/basic-redis-leaderboard-demo-go 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e 7 | github.com/gin-gonic/gin v1.6.3 8 | github.com/go-redis/redis v6.15.9+incompatible 9 | github.com/onsi/ginkgo v1.15.2 // indirect 10 | github.com/onsi/gomega v1.11.0 // indirect 11 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 12 | ) 13 | -------------------------------------------------------------------------------- /controller/company.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type Company struct { 9 | Symbol string `json:"symbol"` 10 | Company string `json:"company"` 11 | Country string `json:"country"` 12 | MarketCap float64 `json:"marketCap"` 13 | Rank int `json:"rank"` 14 | } 15 | 16 | func (c *Company) GetKey() string { 17 | return fmt.Sprintf("leaderboard:%s", strings.ToLower(c.Symbol)) 18 | } 19 | -------------------------------------------------------------------------------- /controller/redis.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | type Redis interface { 4 | HSet(key, field string, value interface{}) error 5 | HGetAll(key string) (map[string]string, error) 6 | ZAdd(key string, member string, score float64) error 7 | ZRevRange(key string, start, stop int64) ([]*Company, error) 8 | ZRange(key string, start, stop int64) ([]*Company, error) 9 | ZScore(key, member string) (float64, error) 10 | ZIncrBy(key string, increment float64, member string) error 11 | ZCount(key, min, max string) (int64, error) 12 | } 13 | -------------------------------------------------------------------------------- /config/redis.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "fmt" 4 | 5 | const ( 6 | defaultConfigRedisPort = 6379 7 | 8 | envConfigRedisHost = "REDIS_HOST" 9 | envConfigRedisPort = "REDIS_PORT" 10 | envConfigRedisPassword = "REDIS_PASSWORD" 11 | ) 12 | 13 | type Redis struct { 14 | host string 15 | port int 16 | password string 17 | } 18 | 19 | func (redis Redis) Addr() string { 20 | return fmt.Sprintf("%s:%d", redis.host, redis.port) 21 | } 22 | 23 | func (redis Redis) Password() string { 24 | return redis.password 25 | } 26 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | redis: 4 | image: redis:6.2.5-alpine 5 | container_name: leaderboard-redis 6 | hostname: leaderboard-redis 7 | restart: always 8 | networks: 9 | - leaderboard-demo 10 | api: 11 | build: 12 | context: . 13 | env_file: 14 | - .env 15 | image: leaderboard-api 16 | container_name: leaderboard-api 17 | ports: 18 | - 8080:8080 19 | volumes: 20 | - ./seed.json:/seed.json 21 | - ./public:/public 22 | restart: always 23 | depends_on: 24 | - redis 25 | networks: 26 | - leaderboard-demo 27 | networks: 28 | leaderboard-demo: 29 | driver: bridge 30 | 31 | -------------------------------------------------------------------------------- /config/api.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "fmt" 4 | 5 | const ( 6 | defaultConfigApiPort = 8080 7 | defaultConfigApiPublicPath = "./public/" 8 | 9 | envConfigApiHost = "API_HOST" 10 | envConfigApiPort = "API_PORT" 11 | envConfigApiPublicPath = "API_PUBLIC_PATH" 12 | envConfigApiTLSDisabled = "API_TLS_DISABLED" 13 | 14 | envExternalConfigApiPort = "PORT" 15 | ) 16 | 17 | type Api struct { 18 | host string 19 | port int 20 | publicPath string 21 | tlsDisabled bool 22 | } 23 | 24 | func (api Api) Addr() string { 25 | return fmt.Sprintf("%s:%d", api.host, api.port) 26 | } 27 | 28 | func (api Api) PublicPath() string { 29 | return api.publicPath 30 | } 31 | 32 | func (api Api) TLSDisabled() bool { 33 | return api.tlsDisabled 34 | } 35 | -------------------------------------------------------------------------------- /internal/waiting.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "os" 7 | "os/signal" 8 | ) 9 | 10 | type Server interface { 11 | Start(ctxCancel context.CancelFunc) 12 | Close() error 13 | } 14 | 15 | type Redis interface { 16 | Close() error 17 | } 18 | 19 | func Waiting(server Server, redis Redis) { 20 | 21 | ctx, ctxCancel := context.WithCancel(context.Background()) 22 | 23 | go server.Start(ctxCancel) 24 | 25 | log.Println("initializing waiting") 26 | 27 | quit := make(chan os.Signal) 28 | signal.Notify(quit, os.Interrupt) 29 | 30 | select { 31 | case <-quit: 32 | log.Println("receive interrupt signal") 33 | if err := server.Close(); err != nil { 34 | log.Println("Server Close:", err) 35 | } 36 | if err := redis.Close(); err != nil { 37 | log.Println("Redis Close:", err) 38 | } 39 | case <-ctx.Done(): 40 | log.Println("shutdown by context") 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/api" 7 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/config" 8 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/controller" 9 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/internal" 10 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/redis" 11 | ) 12 | 13 | func main() { 14 | newConfig := config.NewConfig() 15 | 16 | options, err := redis.NewOptions(newConfig.Redis) 17 | if err != nil { 18 | log.Fatalln(err) 19 | } 20 | 21 | newRedis := redis.New(options) 22 | 23 | newServer := api.NewServer(newConfig.Api) 24 | 25 | controller.SetRedis(newRedis) 26 | 27 | err = controller.ImportCompanies(newConfig.Import.Path(), newRedis) 28 | if err != nil { 29 | log.Fatalln(err) 30 | } 31 | 32 | internal.Waiting(newServer, newRedis) 33 | 34 | log.Println("Server exiting") 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang as builder 2 | 3 | WORKDIR /build 4 | 5 | # Copy the Go Modules manifests 6 | COPY go.mod go.mod 7 | COPY go.sum go.sum 8 | # cache deps before building and copying source so that we don't need to re-download as much 9 | # and so that source changes don't invalidate our downloaded layer 10 | RUN go mod download 11 | 12 | COPY . /build/ 13 | 14 | RUN CGO_ENABLED=0 GOOS=linux go build -o bin . 15 | 16 | # Use distroless as minimal base image to package the manager binary 17 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 18 | FROM gcr.io/distroless/static:nonroot 19 | USER 65532:65532 20 | 21 | ENV PORT=$PORT 22 | ENV API_HOST="" 23 | ENV API_PORT=8080 24 | ENV API_PUBLIC_PATH=/api/public 25 | ENV API_TLS_DISABLED=true 26 | ENV IMPORT_PATH=/api/seed.json 27 | ENV REDIS_HOST="" 28 | ENV REDIS_PORT=6379 29 | ENV REDIS_PASSWORD="" 30 | ENV REDIS_URL="" 31 | 32 | WORKDIR /build 33 | 34 | COPY --from=builder /build/bin /api/ 35 | COPY seed.json /api/ 36 | COPY public /api/public 37 | 38 | WORKDIR /api 39 | 40 | LABEL Name="Leaderboard Api" 41 | 42 | #Run service 43 | ENTRYPOINT ["./bin"] 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Redis Developer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Basic Redis Leaderboard Demo Golang", 3 | "description": "List of top 100 companies", 4 | "stack": "container", 5 | "repository": "https://github.com/redis-developer/basic-redis-leaderboard-demo-go", 6 | "logo": "https://redis.io/images/redis-white.png", 7 | "keywords": ["golang", "gin", "redis", "leadboard"], 8 | "addons": ["rediscloud:30"], 9 | "buildpacks": [ 10 | { 11 | "url": "heroku/python" 12 | } 13 | ], 14 | "env": { 15 | "REDIS_HOST": { 16 | "description": "Redis server host", 17 | "required": true 18 | }, 19 | "REDIS_PORT": { 20 | "description": "Redis server PORT", 21 | "required": true 22 | }, 23 | "REDIS_PASSWORD": { 24 | "description": "Redis server password", 25 | "required": true 26 | }, 27 | "API_PUBLIC_PATH": { 28 | "description": "Public path to frontend, example `/api/public`" 29 | }, 30 | "IMPORT_PATH": { 31 | "description": "Path to seed.json file for import, example `/api/seed.json`" 32 | }, 33 | "API_PORT": { 34 | "description": "Api public port, example `8080`" 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | redis_leaderboard_demo
-------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "strconv" 6 | ) 7 | 8 | type Config struct { 9 | Api *Api 10 | Redis *Redis 11 | Import *Import 12 | } 13 | 14 | func envReadString(envName, defaultValue string) string { 15 | value := os.Getenv(envName) 16 | if value == "" { 17 | value = defaultValue 18 | } 19 | return value 20 | } 21 | 22 | func envReadNumeric(envName string, defaultValue int) int { 23 | value, _ := strconv.Atoi(os.Getenv(envName)) 24 | if value == 0 { 25 | value = defaultValue 26 | } 27 | return value 28 | } 29 | 30 | func envReadBool(envName string) bool { 31 | value, _ := strconv.ParseBool(os.Getenv(envName)) 32 | return value 33 | } 34 | 35 | func NewConfig() *Config { 36 | 37 | apiPort := envReadNumeric(envConfigApiPort, defaultConfigApiPort) 38 | 39 | externalEnvApiPort := os.Getenv(envExternalConfigApiPort) 40 | if externalEnvApiPort != "" { 41 | val, err := strconv.Atoi(externalEnvApiPort) 42 | if err == nil { 43 | apiPort = val 44 | } 45 | } 46 | 47 | config := &Config{ 48 | Api: &Api{ 49 | host: envReadString(envConfigApiHost, ""), 50 | port: apiPort, 51 | publicPath: envReadString(envConfigApiPublicPath, defaultConfigApiPublicPath), 52 | tlsDisabled: envReadBool(envConfigApiTLSDisabled), 53 | }, 54 | Redis: &Redis{ 55 | host: envReadString(envConfigRedisHost, ""), 56 | port: envReadNumeric(envConfigRedisPort, defaultConfigRedisPort), 57 | password: envReadString(envConfigRedisPassword, ""), 58 | }, 59 | Import: &Import{ 60 | path: envReadString(envImportPath, defaultImportPath), 61 | }, 62 | } 63 | 64 | return config 65 | 66 | } 67 | -------------------------------------------------------------------------------- /marketplace.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_name": "Basic Redis leaderboard example in Golang", 3 | "description": "Showcases how to impliment leaderboard appliation in Golang", 4 | "type": "Building Block", 5 | "contributed_by": "Redis", 6 | "repo_url": "https://github.com/redis-developer/basic-redis-leaderboard-demo-go", 7 | "preview_image_url": "https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/images/app_preview_image.png", 8 | "download_url": "https://github.com/redis-developer/basic-redis-leaderboard-demo-go/archive/main.zip", 9 | "hosted_url": "", 10 | "quick_deploy": "true", 11 | "deploy_buttons": [ 12 | { 13 | "heroku": "https://heroku.com/deploy?template=https://github.com/redis-developer/basic-redis-leaderboard-demo-go" 14 | }, 15 | { 16 | "vercel": "https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fredis-developer%2Fbasic-redis-leaderboard-demo-go&env=API_HOST,API_PORT,API_PUBLIC_PATH,REDIS_HOST,REDIS_PORT,REDIS_PASSWORD" 17 | }, 18 | { 19 | "Google": "https://deploy.cloud.run/?git_repo=https://github.com/redis-developer/basic-redis-leaderboard-demo-go.git" 20 | } 21 | ], 22 | "language": [ 23 | "Go" 24 | ], 25 | "redis_commands": [ 26 | "HSET", 27 | "HGETALL", 28 | "ZADD", 29 | "ZREVRANGE", 30 | "ZRANGE", 31 | "ZSCORE", 32 | "ZINCRBY", 33 | "ZCOUNT" 34 | ], 35 | "redis_use_cases": [ 36 | "Leaderboard" 37 | ], 38 | "redis_features": [], 39 | "app_image_urls": [ 40 | "https://github.com/redis-developer/basic-redis-leaderboard-demo-go/blob/master/docs/screenshot001.png?raw=true" 41 | ], 42 | "youtube_url": "https://www.youtube.com/watch?v=zzinHxdZ34I", 43 | "special_tags": [], 44 | "verticals": [ 45 | "Others" 46 | ], 47 | "markdown": "https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/README.md" 48 | } -------------------------------------------------------------------------------- /api/server.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "fmt" 7 | "golang.org/x/crypto/acme/autocert" 8 | "log" 9 | "net/http" 10 | ) 11 | 12 | type Server struct { 13 | srv *http.Server 14 | srvNoTLS *http.Server 15 | } 16 | 17 | func (server Server) Start(ctxCancel context.CancelFunc) { 18 | 19 | if server.srv.TLSConfig != nil { 20 | log.Println(fmt.Sprintf("start server tls listen at [%s]", server.srv.Addr)) 21 | 22 | go func() { 23 | log.Println(fmt.Sprintf("start server tls listen at [%s]", server.srvNoTLS.Addr)) 24 | err := server.srvNoTLS.ListenAndServe() 25 | if err != nil { 26 | log.Println(err) 27 | } 28 | }() 29 | 30 | if err := server.srv.ListenAndServeTLS("", ""); err != nil { 31 | if err == http.ErrServerClosed { 32 | log.Println("server closed under request") 33 | } else { 34 | log.Println("server closed unexpect:", err) 35 | } 36 | } 37 | 38 | } else { 39 | log.Println(fmt.Sprintf("start server listen at [%s]", server.srv.Addr)) 40 | 41 | if err := server.srv.ListenAndServe(); err != nil { 42 | if err == http.ErrServerClosed { 43 | log.Println("server closed under request") 44 | } else { 45 | log.Println("server closed unexpect:", err) 46 | } 47 | } 48 | } 49 | 50 | ctxCancel() 51 | 52 | } 53 | 54 | func (server Server) Close() error { 55 | err1 := server.srv.Close() 56 | if err1 != nil { 57 | log.Println(err1) 58 | } 59 | if server.srvNoTLS != nil { 60 | err2 := server.srvNoTLS.Close() 61 | if err2 != nil { 62 | log.Println(err2) 63 | return err2 64 | } 65 | } 66 | 67 | return err1 68 | 69 | } 70 | 71 | func NewServer(config Config) *Server { 72 | 73 | log.Println("initializing server") 74 | 75 | server := &Server{ 76 | srv: &http.Server{ 77 | Addr: config.Addr(), 78 | Handler: router(config.PublicPath()), 79 | }, 80 | } 81 | 82 | if config.TLSDisabled() == false { 83 | 84 | certManager := autocert.Manager{ 85 | Prompt: autocert.AcceptTOS, 86 | Cache: autocert.DirCache("./certs"), 87 | } 88 | 89 | server.srv.Addr = ":443" 90 | server.srv.TLSConfig = &tls.Config{ 91 | GetCertificate: certManager.GetCertificate, 92 | } 93 | 94 | server.srvNoTLS = &http.Server{ 95 | Addr: ":80", 96 | Handler: certManager.HTTPHandler(nil), 97 | } 98 | 99 | } 100 | 101 | return server 102 | 103 | } 104 | -------------------------------------------------------------------------------- /api/router.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "errors" 5 | "github.com/gin-contrib/static" 6 | "github.com/gin-gonic/gin" 7 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/controller" 8 | "log" 9 | "net/http" 10 | "strconv" 11 | ) 12 | 13 | func router(publicPath string) http.Handler { 14 | 15 | router := gin.Default() 16 | router.Use(static.Serve("/", static.LocalFile(publicPath, true))) 17 | 18 | api := router.Group("/api") 19 | 20 | api.GET("/rank/update", handlerRankUpdate) 21 | 22 | list := api.Group("/list") 23 | 24 | list.GET("/all", handlerAll) 25 | list.GET("/top10", handlerTop10) 26 | list.GET("/bottom10", handlerBottom10) 27 | list.GET("/inRank", handlerInRank) 28 | list.GET("/getBySymbol", handlerGetBySymbol) 29 | 30 | 31 | return router 32 | 33 | } 34 | 35 | func response(c *gin.Context, data interface{}, err error) { 36 | if err != nil { 37 | _ = c.AbortWithError(http.StatusBadRequest, err) 38 | } else { 39 | c.JSON(http.StatusOK, data) 40 | } 41 | } 42 | 43 | func handlerGetBySymbol(c *gin.Context) { 44 | symbols, _ := c.GetQueryArray("symbols[]") 45 | log.Println(symbols) 46 | list, err := controller.Instance().GetBySymbol(symbols) 47 | response(c, list, err) 48 | } 49 | 50 | func handlerInRank(c *gin.Context) { 51 | start, _ := c.GetQuery("start") 52 | end, _ := c.GetQuery("end") 53 | 54 | startInt, _ := strconv.ParseInt(start, 10, 64) 55 | endInt, _ := strconv.ParseInt(end, 10, 64) 56 | 57 | list, err := controller.Instance().InRank(startInt, endInt) 58 | response(c, list, err) 59 | } 60 | 61 | func handlerBottom10(c *gin.Context) { 62 | list, err := controller.Instance().Bottom10() 63 | response(c, list, err) 64 | } 65 | func handlerTop10(c *gin.Context) { 66 | list, err := controller.Instance().Top10() 67 | response(c, list, err) 68 | } 69 | 70 | func handlerAll(c *gin.Context) { 71 | list, err := controller.Instance().All() 72 | response(c, list, err) 73 | } 74 | 75 | func handlerRankUpdate(c *gin.Context) { 76 | symbol, ok := c.GetQuery("symbol") 77 | if !ok { 78 | response(c, "not found symbol", errors.New("not found symbol")) 79 | return 80 | } 81 | 82 | amount, ok := c.GetQuery("amount") 83 | if !ok { 84 | response(c, "not found symbol", errors.New("not found symbol")) 85 | return 86 | } 87 | 88 | amountFloat,err := strconv.ParseFloat(amount, 64) 89 | if err != nil { 90 | response(c, "could not convert amount to float64", err) 91 | return 92 | } 93 | 94 | err = controller.Instance().UpdateRank(symbol, amountFloat) 95 | if err != nil { 96 | response(c, "could not update rank", err) 97 | } 98 | 99 | c.Status(http.StatusAccepted) 100 | 101 | } -------------------------------------------------------------------------------- /redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | 10 | "github.com/go-redis/redis" 11 | "github.com/redis-developer/basic-redis-leaderboard-demo-go/controller" 12 | ) 13 | 14 | const envRedisURL = "REDIS_URL" 15 | 16 | type Value struct { 17 | Score float64 18 | } 19 | 20 | type Redis struct { 21 | client *redis.Client 22 | } 23 | 24 | func (r Redis) HGetAll(key string) (map[string]string, error) { 25 | return r.client.HGetAll(key).Result() 26 | } 27 | 28 | func (r Redis) HSet(key, field string, value interface{}) error { 29 | return r.client.HSet(key, field, value).Err() 30 | } 31 | 32 | func (r Redis) ZAdd(key string, member string, score float64) error { 33 | return r.client.ZAdd(key, redis.Z{Member: member, Score: score}).Err() 34 | } 35 | func (r Redis) ZRevRange(key string, start, stop int64) ([]*controller.Company, error) { 36 | z, err := r.client.ZRevRangeWithScores(key, start, stop).Result() 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | companies := make([]*controller.Company, 0, len(z)) 42 | 43 | for i := range z { 44 | companies = append(companies, &controller.Company{ 45 | Symbol: z[i].Member.(string), 46 | MarketCap: z[i].Score, 47 | }) 48 | //values[z[i].Member.(string)] = z[i].Score 49 | } 50 | 51 | return companies, nil 52 | 53 | } 54 | 55 | func (r Redis) ZRange(key string, start, stop int64) ([]*controller.Company, error) { 56 | z, err := r.client.ZRangeWithScores(key, start, stop).Result() 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | n := len(z) 62 | companies := make([]*controller.Company, 0, n) 63 | 64 | for i := range z { 65 | companies = append(companies, &controller.Company{ 66 | Symbol: z[n-i-1].Member.(string), 67 | MarketCap: z[n-i-1].Score, 68 | }) 69 | } 70 | return companies, err 71 | } 72 | 73 | func (r Redis) ZScore(key, member string) (float64, error) { 74 | return r.client.ZScore(key, member).Result() 75 | } 76 | 77 | func (r Redis) ZIncrBy(key string, increment float64, member string) error { 78 | return r.client.ZIncrBy(key, increment, member).Err() 79 | } 80 | 81 | func (r Redis) ZCount(key, min, max string) (int64, error) { 82 | return r.client.ZCount(key, min, max).Result() 83 | } 84 | 85 | func (r Redis) Close() error { 86 | return r.client.Close() 87 | } 88 | 89 | func NewOptions(config Config) (opt *redis.Options, err error) { 90 | // read options from Redis URL 91 | url, ok := os.LookupEnv(envRedisURL) 92 | if ok && url != "" { 93 | // ref https://pkg.go.dev/github.com/go-redis/redis?utm_source=gopls#ParseURL 94 | opt, err = redis.ParseURL(url) 95 | if err != nil { 96 | return nil, err 97 | } 98 | } else { 99 | // read options from config 100 | opt = &redis.Options{ 101 | Addr: config.Addr(), 102 | Password: config.Password(), 103 | } 104 | } 105 | 106 | // read CA cert 107 | caPath, ok := os.LookupEnv("TLS_CA_CERT_FILE") 108 | if ok && caPath != "" { 109 | // ref https://pkg.go.dev/crypto/tls#example-Dial 110 | rootCertPool := x509.NewCertPool() 111 | pem, err := ioutil.ReadFile(caPath) 112 | if err != nil { 113 | return nil, err 114 | } 115 | if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { 116 | return nil, fmt.Errorf("Failed to append root CA cert at %s", caPath) 117 | } 118 | opt.TLSConfig = &tls.Config{ 119 | RootCAs: rootCertPool, 120 | } 121 | 122 | // https://pkg.go.dev/crypto/tls#LoadX509KeyPair 123 | clientCert, ok := os.LookupEnv("TLS_CERT_FILE") 124 | clientKey, ok2 := os.LookupEnv("TLS_KEY_FILE") 125 | if ok && ok2 { 126 | cert, err := tls.LoadX509KeyPair(clientCert, clientKey) 127 | if err != nil { 128 | return nil, err 129 | } 130 | opt.TLSConfig.Certificates = []tls.Certificate{cert} 131 | opt.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert 132 | opt.TLSConfig.ClientCAs = rootCertPool 133 | } 134 | } 135 | 136 | return opt, nil 137 | } 138 | 139 | func New(opt *redis.Options) *Redis { 140 | client := redis.NewClient(opt) 141 | 142 | return &Redis{ 143 | client: client, 144 | } 145 | } 146 | 147 | func NewRedisFromOptions(opt *redis.Options) *Redis { 148 | client := redis.NewClient(opt) 149 | 150 | return &Redis{ 151 | client: client, 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/go-redis/redis" 6 | "log" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | const ( 12 | keyPrefixCompany = "leaderboard:" 13 | keyLeaderBoard = "REDIS_LEADERBOARD" 14 | ) 15 | 16 | type Controller struct { 17 | r Redis 18 | } 19 | 20 | func (c Controller) sort(companies []*Company) { 21 | 22 | for i := range companies { 23 | for j := range companies { 24 | if companies[i].Rank < companies[j].Rank { 25 | a := *companies[i] 26 | b := *companies[j] 27 | *companies[i] = b 28 | *companies[j] = a 29 | } 30 | } 31 | } 32 | } 33 | 34 | func (c Controller) buildRanks(companies []*Company) { 35 | allCompanies, err := c.r.ZRevRange(keyLeaderBoard, 0, -1) 36 | if err != nil { 37 | log.Println(err) 38 | } 39 | ranks := make(map[string]int, len(allCompanies)) 40 | for i := range allCompanies { 41 | key := allCompanies[i].GetKey() 42 | ranks[key] = i + 1 43 | } 44 | for i := range companies { 45 | if rank, ok := ranks[companies[i].GetKey()]; ok { 46 | companies[i].Rank = rank 47 | } 48 | } 49 | } 50 | 51 | func (c Controller) buildCompany(company *Company) { 52 | key := company.GetKey() 53 | data, err := c.r.HGetAll(key) 54 | if err == redis.Nil { 55 | return 56 | } else if err != nil { 57 | log.Println(err) 58 | return 59 | } 60 | 61 | company.Symbol = data["symbol"] 62 | company.Company = data["company"] 63 | company.Country = data["country"] 64 | } 65 | 66 | func (c Controller) buildCompanies(companies []*Company) { 67 | for i := range companies { 68 | companies[i].Rank = i + 1 69 | c.buildCompany(companies[i]) 70 | } 71 | } 72 | 73 | func (c Controller) All() ([]*Company, error) { 74 | companies, err := c.r.ZRevRange(keyLeaderBoard, 0, -1) 75 | if err != nil { 76 | return nil, err 77 | } 78 | c.buildCompanies(companies) 79 | return companies, nil 80 | } 81 | 82 | func (c Controller) Top10() ([]*Company, error) { 83 | companies, err := c.r.ZRevRange(keyLeaderBoard, 0, 9) 84 | if err != nil { 85 | return nil, err 86 | } 87 | c.buildCompanies(companies) 88 | c.buildRanks(companies) 89 | return companies, nil 90 | } 91 | 92 | func (c Controller) Bottom10() ([]*Company, error) { 93 | companies, err := c.r.ZRange(keyLeaderBoard, 0, 9) 94 | if err != nil { 95 | return nil, err 96 | } 97 | c.buildCompanies(companies) 98 | c.buildRanks(companies) 99 | return companies, nil 100 | } 101 | 102 | func (c Controller) InRank(start, end int64) ([]*Company, error) { 103 | companies, err := c.r.ZRevRange(keyLeaderBoard, start, end) 104 | if err != nil { 105 | return nil, err 106 | } 107 | c.buildCompanies(companies) 108 | c.buildRanks(companies) 109 | c.sort(companies) 110 | return companies, nil 111 | } 112 | 113 | func (c Controller) GetBySymbol(symbols []string) ([]*Company, error) { 114 | companies := make([]*Company, 0, len(symbols)) 115 | 116 | for i := range symbols { 117 | score, err := c.r.ZScore(keyLeaderBoard, strings.ToLower(symbols[i])) 118 | if err != nil { 119 | return nil, err 120 | } 121 | 122 | company := &Company{ 123 | Symbol: symbols[i], 124 | MarketCap: score, 125 | } 126 | 127 | c.buildCompany(company) 128 | 129 | companies = append(companies, company) 130 | } 131 | c.buildRanks(companies) 132 | c.sort(companies) 133 | return companies, nil 134 | } 135 | 136 | func (c Controller) UpdateRank(symbol string, amount float64) error { 137 | err := c.r.ZIncrBy(keyLeaderBoard, amount, symbol) 138 | if err != nil { 139 | return err 140 | } 141 | return nil 142 | } 143 | 144 | var controller = &Controller{} 145 | 146 | func Instance() *Controller { 147 | return controller 148 | } 149 | 150 | func ImportCompanies(filePath string, r Redis) error { 151 | fp, err := os.OpenFile(filePath, os.O_RDONLY, 0644) 152 | if err != nil { 153 | return err 154 | } 155 | defer fp.Close() 156 | 157 | companies := make([]Company, 0) 158 | dec := json.NewDecoder(fp) 159 | err = dec.Decode(&companies) 160 | if err != nil { 161 | return err 162 | } 163 | 164 | for i := range companies { 165 | 166 | if err := r.ZAdd(keyLeaderBoard, strings.ToLower(companies[i].Symbol), companies[i].MarketCap); err != nil { 167 | return err 168 | } 169 | 170 | if err := r.HSet(companies[i].GetKey(), "symbol", strings.ToLower(companies[i].Symbol)); err != nil { 171 | return err 172 | } 173 | if err := r.HSet(companies[i].GetKey(), "company", companies[i].Company); err != nil { 174 | return err 175 | } 176 | if err := r.HSet(companies[i].GetKey(), "country", companies[i].Country); err != nil { 177 | return err 178 | } 179 | } 180 | 181 | return err 182 | } 183 | 184 | func SetRedis(redis Redis) { 185 | controller.r = redis 186 | } 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic Redis Leaderboard Demo Golang 2 | 3 | Show how the Redis works with Golang. 4 | 5 | 6 | # How it works? 7 | 8 | ![https://raw.githubusercontent.com/redis-developer](https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image5.jpg?v=2&s=2) 9 | 10 | ## How the data is stored: 11 | 12 | - The AAPL's details - market cap of 2,6 triillions and USA origin - are stored in a hash like below: 13 | - E.g `HSET "company:AAPL" symbol "AAPL" market_cap "2600000000000" country USA` 14 | - The Ranks of AAPL of 2,6 trillions are stored in a ZSET. 15 | - E.g `ZADD companyLeaderboard 2600000000000 company:AAPL` 16 | 17 | ## How the data is accessed: 18 | 19 | - Top 10 companies: 20 | - E.g `ZREVRANGE companyLeaderboard 0 9 WITHSCORES` 21 | - All companies: 22 | - E.g `ZREVRANGE companyLeaderboard 0 -1 WITHSCORES` 23 | - Bottom 10 companies: 24 | - E.g `ZRANGE companyLeaderboard 0 9 WITHSCORES` 25 | - Between rank 10 and 15: 26 | - E.g `ZREVRANGE companyLeaderboard 9 14 WITHSCORES` 27 | - Show ranks of AAPL, FB and TSLA: 28 | - E.g `ZSCORE companyLeaderBoard company:AAPL company:FB company:TSLA` 29 | - Adding market cap to companies: 30 | - E.g `ZINCRBY companyLeaderBoard 1000000000 "company:FB"` 31 | - Reducing market cap to companies: 32 | - E.g `ZINCRBY companyLeaderBoard -1000000000 "company:FB"` 33 | - Companies over a Trillion: 34 | - E.g `ZCOUNT companyLeaderBoard 1000000000000 +inf` 35 | - Companies between 500 billion and 1 trillion: 36 | - E.g `ZCOUNT companyLeaderBoard 500000000000 1000000000000` 37 | 38 | ### Code Example: Get top 10 companies 39 | 40 | ```Go 41 | func (c Controller) Top10() ([]*Company, error) { 42 | companies, err := c.r.ZRevRange(keyLeaderBoard, 0, 9) 43 | if err != nil { 44 | return nil, err 45 | } 46 | c.buildCompanies(companies) 47 | c.buildRanks(companies) 48 | return companies, nil 49 | } 50 | ``` 51 | 52 | ## How to run it locally? 53 | 54 | #### Copy `.env.example` to create `.env`. And provide the values for environment variables if needed 55 | 56 | - REDIS_HOST: Redis server host 57 | - REDIS_PORT: Redis server port 58 | - REDIS_PASSWORD: Password to the server 59 | 60 | ### Configure by an environment variable with Redis connection string URL 61 | 62 | It is possible to pass any valid Redis URL for Redis options as in [ParseURL Example](https://pkg.go.dev/github.com/go-redis/redis?utm_source=gopls#example-ParseURL) 63 | This way REDIS_HOST, REDIS_PORT, REDIS_PASSWORD are not needed. 64 | 65 | - REDIS_URL=redis :// [[username :] password@] host [:port][/database] 66 | - Example REDIS_URL="redis://p%40ssw0rd@redis-16379.hosted.com:16379/0" from [redis-cli, the Redis command line interface](https://redis.io/topics/rediscli) 67 | 68 | Scheme syntax: 69 | Example: redis://user:secret@localhost:6379/0?foo=bar&qux=baz 70 | 71 | This scheme uses a profile of the RFC 3986 generic URI syntax. 72 | All URI fields after the scheme are optional. 73 | The "userinfo" field uses the traditional "user:password" format. 74 | 75 | From [Provisional RFC for Redis URIs](https://www.iana.org/assignments/uri-schemes/prov/redis) 76 | 77 | ### Secure a connection with Redis with a mutual TLS 78 | 79 | To support this feature three new environment variables are introduced, TLS_CA_CERT_FILE, TLS_CERT_FILE, TLS_KEY_FILE. Their names are the same as "redis.conf" is using. They contain paths to respective files in a mounted secret volume. To use it with Kubernetes pods, add this to a container configuration: 80 | 81 | ```yaml 82 | spec: 83 | containers: 84 | - env: 85 | - name: TLS_CA_CERT_FILE 86 | value: /certs/ca.crt # path to CA certificate 87 | - name: TLS_CERT_FILE 88 | value: /certs/tls.crt # path to client certificate 89 | - name: TLS_KEY_FILE 90 | value: /certs/tls.key # path to client key 91 | image: ghcr.io/denist-huma/basic-redis-leaderboard-demo-go:1.2.2 92 | name: leaderboard-tls 93 | ports: 94 | - containerPort: 8080 95 | protocol: TCP 96 | volumeMounts: 97 | - mountPath: /certs 98 | name: leaderboard-tls-redis-client-cert 99 | 100 | volumes: 101 | - name: leaderboard-tls-redis-client-cert 102 | secret: 103 | defaultMode: 420 104 | secretName: leaderboard-tls-redis-client-cert 105 | ``` 106 | 107 | Where the secret "leaderboard-tls-redis-client-cert" has all three files we need. Here is a mere description, not the actual data: 108 | 109 | ```yaml 110 | apiVersion: v1 111 | data: 112 | tls.crt: 1261 bytes 113 | tls.key: 1679 bytes 114 | ca.crt: 1415 bytes 115 | kind: Secret 116 | metadata: 117 | name: leaderboard-tls-redis-client-cert 118 | type: kubernetes.io/tls 119 | ``` 120 | 121 | #### Run demo 122 | 123 | ```sh 124 | go get 125 | go run 126 | ``` 127 | 128 | Follow: http://localhost:8080 129 | 130 | ## Try it out 131 | 132 |

133 | 134 | Deploy to Heroku 135 | 136 |

137 | 138 |

139 | 140 | Run on Google Cloud 141 | 142 | 143 | (See notes: How to run on Google Cloud) 144 | 145 |

146 | 147 | ## How to run on Google Cloud 148 | 149 | ## 1. Click "Run on Google Cloud" 150 | 151 | Add the right values as per your infrastructure: 152 | 153 | ``` 154 | [ ? ] Value of REDIS_HOST environment variable (Redis server host) 155 | [ ? ] Value of REDIS_PORT environment variable (Redis server PORT) 156 | [ ? ] Value of REDIS_PASSWORD environment variable (Redis server password) 157 | [ ? ] Value of API_PUBLIC_PATH environment variable (Public path to frontend, example `/api/public`) /api/ 158 | [ ? ] Value of IMPORT_PATH environment variable (Path to seed.json file for import, example `/api/seed.json`) seed.json 159 | [ ? ] Value of API_PORT environment variable (Api public port, example `8080`) 8080 160 | ``` 161 | 162 | 163 | Open up the link under "Manage this application at Cloud Console" to open up "Edit and Deploy New Revision” 164 | 165 | ## 2. Click “Variables and Secrets” 166 | 167 | 168 | ![](https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image4.jpg?v=2&s=2) 169 | 170 | ## 3. Verify the connector 171 | 172 | ![](https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image2.jpg?v=2&s=2) 173 | 174 | ## 3. Access the app 175 | 176 | ![](https://raw.githubusercontent.com/redis-developer/basic-redis-leaderboard-demo-go/master/image5.jpg?v=2&s=2) 177 | 178 | Hence, you should be able to access this app 179 | -------------------------------------------------------------------------------- /public/js/app.d61e56cf.js: -------------------------------------------------------------------------------- 1 | (function(e){function t(t){for(var n,i,l=t[0],c=t[1],s=t[2],u=0,d=[];uO?"$".concat((e/O).toFixed(3)," T"):e>L?"$".concat((e/L).toFixed(2)," B"):e>F?"$".concat((e/F).toFixed(1)," M"):"$ ".concat(e)},getCountryFlag:function(e){var t={"S. Arabia":"Saudi Arabia","S. Korea":"South Korea"},a=Object(u["findFlagUrlByCountryName"])(t[e]||e);return a}}},E=B,U=(a("1e58"),a("62ad")),j=a("a523"),N=a("8fea"),I=a("cd55"),$=a("49e2"),D=a("c865"),H=a("0393"),Z=a("0fd9"),M=Object(h["a"])(E,i,l,!1,null,"6d7466c0",null),G=M.exports;x()(M,{VBtn:_["a"],VCard:k["a"],VCol:U["a"],VContainer:j["a"],VDataTable:N["a"],VExpansionPanel:I["a"],VExpansionPanelContent:$["a"],VExpansionPanelHeader:D["a"],VExpansionPanels:H["a"],VIcon:w["a"],VRow:Z["a"],VSelect:R["a"]});var K={name:"App",components:{Example:G}},W=K,z=(a("034f"),a("7496")),J=Object(h["a"])(W,o,r,!1,null,null,null),Y=J.exports;x()(J,{VApp:z["a"]});var q=a("f309");n["a"].use(q["a"]);var Q=new q["a"]({});n["a"].config.productionTip=!1,new n["a"]({vuetify:Q,render:function(e){return e(Y)}}).$mount("#app")},"85ec":function(e,t,a){}}); 2 | //# sourceMappingURL=app.d61e56cf.js.map -------------------------------------------------------------------------------- /seed.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "company": "Apple", 3 | "symbol": "AAPL", 4 | "marketCap": 2222000000, 5 | "country": "USA" 6 | }, { 7 | "company": "Saudi Aramco", 8 | "symbol": "2222.SR", 9 | "marketCap": 2046000000, 10 | "country": "S. Arabia" 11 | }, { 12 | "company": "Microsoft", 13 | "symbol": "MSFT", 14 | "marketCap": 1660000000, 15 | "country": "USA" 16 | }, { 17 | "company": "Amazon", 18 | "symbol": "AMZN", 19 | "marketCap": 1597000000, 20 | "country": "USA" 21 | }, { 22 | "company": "Alphabet (Google)", 23 | "symbol": "GOOG", 24 | "marketCap": 1218000000, 25 | "country": "USA" 26 | }, { 27 | "company": "Tesla", 28 | "symbol": "TSLA", 29 | "marketCap": 834170000, 30 | "country": "USA" 31 | }, { 32 | "company": "Facebook", 33 | "symbol": "FB", 34 | "marketCap": 762110000, 35 | "country": "USA" 36 | }, { 37 | "company": "Tencent", 38 | "symbol": "TCEHY", 39 | "marketCap": 742230000, 40 | "country": "China" 41 | }, { 42 | "company": "Alibaba", 43 | "symbol": "BABA", 44 | "marketCap": 642220000, 45 | "country": "China" 46 | }, { 47 | "company": "Berkshire Hathaway", 48 | "symbol": "BRK-A", 49 | "marketCap": 549580000, 50 | "country": "USA" 51 | }, { 52 | "company": "Samsung", 53 | "symbol": "005930.KS", 54 | "marketCap": 526630000, 55 | "country": "S. Korea" 56 | }, { 57 | "company": "TSMC", 58 | "symbol": "TSM", 59 | "marketCap": 511700000, 60 | "country": "Taiwan" 61 | }, { 62 | "company": "Visa", 63 | "symbol": "V", 64 | "marketCap": 474940000, 65 | "country": "USA" 66 | }, { 67 | "company": "Johnson & Johnson", 68 | "symbol": "JNJ", 69 | "marketCap": 421310000, 70 | "country": "USA" 71 | }, { 72 | "company": "Walmart", 73 | "symbol": "WMT", 74 | "marketCap": 414850000, 75 | "country": "USA" 76 | }, { 77 | "company": "JPMorgan Chase", 78 | "symbol": "JPM", 79 | "marketCap": 414610000, 80 | "country": "USA" 81 | }, { 82 | "company": "Kweichow Moutai", 83 | "symbol": "600519.SS", 84 | "marketCap": 392630000, 85 | "country": "China" 86 | }, { 87 | "company": "Mastercard", 88 | "symbol": "MA", 89 | "marketCap": 352760000, 90 | "country": "USA" 91 | }, { 92 | "company": "UnitedHealth", 93 | "symbol": "UNH", 94 | "marketCap": 344790000, 95 | "country": "USA" 96 | }, { 97 | "company": "Procter & Gamble", 98 | "symbol": "PG", 99 | "marketCap": 344140000, 100 | "country": "USA" 101 | }, { 102 | "company": "Nestlé", 103 | "symbol": "NSRGY", 104 | "marketCap": 333610000, 105 | "country": "Switzerland" 106 | }, { 107 | "company": "NVIDIA", 108 | "symbol": "NVDA", 109 | "marketCap": 328730000, 110 | "country": "USA" 111 | }, { 112 | "company": "LVMH", 113 | "symbol": "LVMUY", 114 | "marketCap": 327040000, 115 | "country": "France" 116 | }, { 117 | "company": "Walt Disney", 118 | "symbol": "DIS", 119 | "marketCap": 322900000, 120 | "country": "USA" 121 | }, { 122 | "company": "Roche", 123 | "symbol": "RHHBY", 124 | "marketCap": 293520000, 125 | "country": "Switzerland" 126 | }, { 127 | "company": "Home Depot", 128 | "symbol": "HD", 129 | "marketCap": 289700000, 130 | "country": "USA" 131 | }, { 132 | "company": "PayPal", 133 | "symbol": "PYPL", 134 | "marketCap": 284080000, 135 | "country": "USA" 136 | }, { 137 | "company": "Bank of America", 138 | "symbol": "BAC", 139 | "marketCap": 281410000, 140 | "country": "USA" 141 | }, { 142 | "company": "ICBC", 143 | "symbol": "1398.HK", 144 | "marketCap": 266230000, 145 | "country": "China" 146 | }, { 147 | "company": "Meituan-Dianping", 148 | "symbol": "MPNGF", 149 | "marketCap": 246210000, 150 | "country": "China" 151 | }, { 152 | "company": "Verizon", 153 | "symbol": "VZ", 154 | "marketCap": 239180000, 155 | "country": "USA" 156 | }, { 157 | "company": "Ping An Insurance", 158 | "symbol": "PNGAY", 159 | "marketCap": 237140000, 160 | "country": "China" 161 | }, { 162 | "company": "Comcast", 163 | "symbol": "CMCSA", 164 | "marketCap": 235810000, 165 | "country": "USA" 166 | }, { 167 | "company": "Adobe", 168 | "symbol": "ADBE", 169 | "marketCap": 232710000, 170 | "country": "USA" 171 | }, { 172 | "company": "Nike", 173 | "symbol": "NKE", 174 | "marketCap": 230710000, 175 | "country": "USA" 176 | }, { 177 | "company": "Netflix", 178 | "symbol": "NFLX", 179 | "marketCap": 225490000, 180 | "country": "USA" 181 | }, { 182 | "company": "Pinduoduo", 183 | "symbol": "PDD", 184 | "marketCap": 221680000, 185 | "country": "China" 186 | }, { 187 | "company": "Coca-Cola", 188 | "symbol": "KO", 189 | "marketCap": 219510000, 190 | "country": "USA" 191 | }, { 192 | "company": "Novartis", 193 | "symbol": "NVS", 194 | "marketCap": 214590000, 195 | "country": "Switzerland" 196 | }, { 197 | "company": "Toyota", 198 | "symbol": "TM", 199 | "marketCap": 212390000, 200 | "country": "Japan" 201 | }, { 202 | "company": "ASML", 203 | "symbol": "ASML", 204 | "marketCap": 212100000, 205 | "country": "Netherlands" 206 | }, { 207 | "company": "Intel", 208 | "symbol": "INTC", 209 | "marketCap": 211660000, 210 | "country": "USA" 211 | }, { 212 | "company": "L' Oréal", 213 | "symbol": "OR.PA", 214 | "marketCap": 210160000, 215 | "country": "France" 216 | }, { 217 | "company": "Merck", 218 | "symbol": "MRK", 219 | "marketCap": 210060000, 220 | "country": "USA" 221 | }, { 222 | "company": "AT&T", 223 | "symbol": "T", 224 | "marketCap": 206790000, 225 | "country": "USA" 226 | }, { 227 | "company": "Pfizer", 228 | "symbol": "PFE", 229 | "marketCap": 206380000, 230 | "country": "USA" 231 | }, { 232 | "company": "Salesforce", 233 | "symbol": "CRM", 234 | "marketCap": 203770000, 235 | "country": "USA" 236 | }, { 237 | "company": "Thermo Fisher Scientific", 238 | "symbol": "TMO", 239 | "marketCap": 203040000, 240 | "country": "USA" 241 | }, { 242 | "company": "Pepsico", 243 | "symbol": "PEP", 244 | "marketCap": 199250000, 245 | "country": "USA" 246 | }, { 247 | "company": "Abbott Laboratories", 248 | "symbol": "ABT", 249 | "marketCap": 197810000, 250 | "country": "USA" 251 | }, { 252 | "company": "China Construction Bank", 253 | "symbol": "CICHY", 254 | "marketCap": 193710000, 255 | "country": "China" 256 | }, { 257 | "company": "Exxon Mobil", 258 | "symbol": "XOM", 259 | "marketCap": 192210000, 260 | "country": "USA" 261 | }, { 262 | "company": "Oracle", 263 | "symbol": "ORCL", 264 | "marketCap": 190830000, 265 | "country": "USA" 266 | }, { 267 | "company": "Cisco", 268 | "symbol": "CSCO", 269 | "marketCap": 190400000, 270 | "country": "USA" 271 | }, { 272 | "company": "AbbVie", 273 | "symbol": "ABBV", 274 | "marketCap": 189380000, 275 | "country": "USA" 276 | }, { 277 | "company": "BHP Group", 278 | "symbol": "BHP", 279 | "marketCap": 186040000, 280 | "country": "Australia" 281 | }, { 282 | "company": "Broadcom", 283 | "symbol": "AVGO", 284 | "marketCap": 181240000, 285 | "country": "USA" 286 | }, { 287 | "company": "CM Bank", 288 | "symbol": "3968.HK", 289 | "marketCap": 180460000, 290 | "country": "China" 291 | }, { 292 | "company": "QUALCOMM", 293 | "symbol": "QCOM", 294 | "marketCap": 177150000, 295 | "country": "USA" 296 | }, { 297 | "company": "Reliance Industries", 298 | "symbol": "RELIANCE.NS", 299 | "marketCap": 177100000, 300 | "country": "India" 301 | }, { 302 | "company": "Chevron", 303 | "symbol": "CVX", 304 | "marketCap": 175320000, 305 | "country": "USA" 306 | }, { 307 | "company": "Accenture", 308 | "symbol": "ACN", 309 | "marketCap": 175020000, 310 | "country": "Ireland" 311 | }, { 312 | "company": "Danaher", 313 | "symbol": "DHR", 314 | "marketCap": 172960000, 315 | "country": "USA" 316 | }, { 317 | "company": "Agricultural Bank of China", 318 | "symbol": "ACGBY", 319 | "marketCap": 168730000, 320 | "country": "China" 321 | }, { 322 | "company": "T-Mobile US", 323 | "symbol": "TMUS", 324 | "marketCap": 167630000, 325 | "country": "USA" 326 | }, { 327 | "company": "Prosus", 328 | "symbol": "PRX.VI", 329 | "marketCap": 165690000, 330 | "country": "Netherlands" 331 | }, { 332 | "company": "Costco", 333 | "symbol": "COST", 334 | "marketCap": 163860000, 335 | "country": "USA" 336 | }, { 337 | "company": "Novo Nordisk", 338 | "symbol": "NVO", 339 | "marketCap": 162260000, 340 | "country": "Denmark" 341 | }, { 342 | "company": "Medtronic", 343 | "symbol": "MDT", 344 | "marketCap": 161130000, 345 | "country": "Ireland" 346 | }, { 347 | "company": "McDonald", 348 | "symbol": "MCD", 349 | "marketCap": 160840000, 350 | "country": "USA" 351 | }, { 352 | "company": "Unilever", 353 | "symbol": "UL", 354 | "marketCap": 160420000, 355 | "country": "Netherlands" 356 | }, { 357 | "company": "Eli Lilly", 358 | "symbol": "LLY", 359 | "marketCap": 159180000, 360 | "country": "USA" 361 | }, { 362 | "company": "Nextera Energy", 363 | "symbol": "NEE", 364 | "marketCap": 158930000, 365 | "country": "USA" 366 | }, { 367 | "company": "Texas Instruments", 368 | "symbol": "TXN", 369 | "marketCap": 157110000, 370 | "country": "USA" 371 | }, { 372 | "company": "SAP", 373 | "symbol": "SAP", 374 | "marketCap": 156750000, 375 | "country": "Germany" 376 | }, { 377 | "company": "Tata", 378 | "symbol": "TCS.NS", 379 | "marketCap": 156350000, 380 | "country": "India" 381 | }, { 382 | "company": "Shell", 383 | "symbol": "RYDAF", 384 | "marketCap": 155950000, 385 | "country": "Netherlands" 386 | }, { 387 | "company": "AIA", 388 | "symbol": "AAIGF", 389 | "marketCap": 153920000, 390 | "country": "Hong Kong" 391 | }, { 392 | "company": "Union Pacific Corporation", 393 | "symbol": "UNP", 394 | "marketCap": 147450000, 395 | "country": "USA" 396 | }, { 397 | "company": "Honeywell", 398 | "symbol": "HON", 399 | "marketCap": 147370000, 400 | "country": "USA" 401 | }, { 402 | "company": "Jingdong Mall", 403 | "symbol": "JD", 404 | "marketCap": 146600000, 405 | "country": "China" 406 | }, { 407 | "company": "Shopify", 408 | "symbol": "SHOP", 409 | "marketCap": 145120000, 410 | "country": "Canada" 411 | }, { 412 | "company": "SoftBank", 413 | "symbol": "SFTBF", 414 | "marketCap": 143310000, 415 | "country": "Japan" 416 | }, { 417 | "company": "China Life Insurance", 418 | "symbol": "LFC", 419 | "marketCap": 142650000, 420 | "country": "China" 421 | }, { 422 | "company": "Linde", 423 | "symbol": "LIN", 424 | "marketCap": 141920000, 425 | "country": "UK" 426 | }, { 427 | "company": "Anheuser-Busch Inbev", 428 | "symbol": "BUD", 429 | "marketCap": 141810000, 430 | "country": "Belgium" 431 | }, { 432 | "company": "Bristol-Myers Squibb", 433 | "symbol": "BMY", 434 | "marketCap": 141210000, 435 | "country": "USA" 436 | }, { 437 | "company": "Amgen", 438 | "symbol": "AMGN", 439 | "marketCap": 138840000, 440 | "country": "USA" 441 | }, { 442 | "company": "Keyence", 443 | "symbol": "KYCCF", 444 | "marketCap": 137430000, 445 | "country": "Japan" 446 | }, { 447 | "company": "Wells Fargo", 448 | "symbol": "WFC", 449 | "marketCap": 137220000, 450 | "country": "USA" 451 | }, { 452 | "company": "United Parcel Service", 453 | "symbol": "UPS", 454 | "marketCap": 136910000, 455 | "country": "USA" 456 | }, { 457 | "company": "Morgan Stanley", 458 | "symbol": "MS", 459 | "marketCap": 136140000, 460 | "country": "USA" 461 | }, { 462 | "company": "Citigroup", 463 | "symbol": "C", 464 | "marketCap": 136090000, 465 | "country": "USA" 466 | }, { 467 | "company": "Astrazeneca", 468 | "symbol": "AZN", 469 | "marketCap": 135460000, 470 | "country": "UK" 471 | }, { 472 | "company": "Bank of China", 473 | "symbol": "BACHF", 474 | "marketCap": 132660000, 475 | "country": "China" 476 | }, { 477 | "company": "Philip Morris", 478 | "symbol": "PM", 479 | "marketCap": 129390000, 480 | "country": "USA" 481 | }, { 482 | "company": "Sony", 483 | "symbol": "SNE", 484 | "marketCap": 127620000, 485 | "country": "Japan" 486 | }, { 487 | "company": "Charter Communications", 488 | "symbol": "CHTR", 489 | "marketCap": 126790000, 490 | "country": "USA" 491 | }, { 492 | "company": "Starbucks", 493 | "symbol": "SBUX", 494 | "marketCap": 124020000, 495 | "country": "USA" 496 | }, { 497 | "company": "NTT Docomo", 498 | "symbol": "NTDMF", 499 | "marketCap": 122470000, 500 | "country": "Japan" 501 | }] -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= 5 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 6 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 7 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 8 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 9 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 10 | github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e h1:8bZpGwoPxkaivQPrAbWl+7zjjUcbFUnYp7yQcx2r2N0= 11 | github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e/go.mod h1:VhW/Ch/3FhimwZb8Oj+qJmdMmoB8r7lmJ5auRjm50oQ= 12 | github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= 13 | github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= 14 | github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= 15 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 16 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 17 | github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= 18 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 19 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 20 | github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= 21 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 22 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 23 | github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= 24 | github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= 25 | github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= 26 | github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 27 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 28 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 29 | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= 30 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 31 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 32 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 33 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 34 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 35 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 36 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 37 | github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 38 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 39 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 40 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 41 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 42 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 43 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 44 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 45 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 46 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 47 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 48 | github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= 49 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 50 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 51 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 52 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 53 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 54 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 55 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 56 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 57 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 58 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 59 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 60 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 61 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 62 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 63 | github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= 64 | github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= 65 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 66 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 67 | github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= 68 | github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= 69 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 70 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 71 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 72 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 73 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 74 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 75 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 76 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 77 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 78 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 79 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 80 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 81 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 82 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= 83 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 84 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= 85 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 86 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 87 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 88 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 89 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 90 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 91 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 92 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= 93 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 94 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 95 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 96 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 97 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 98 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 99 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 100 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 101 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 102 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 103 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 104 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 105 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 106 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= 107 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 108 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 109 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 110 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 111 | golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= 112 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 113 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 114 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 115 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 116 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= 117 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 118 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 119 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 120 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 121 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 122 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 123 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 124 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 125 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 126 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 127 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 128 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 129 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 130 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 131 | google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= 132 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 133 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 134 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 135 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 136 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 137 | gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= 138 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 139 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 140 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 141 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 142 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 143 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 144 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 145 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 146 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 147 | -------------------------------------------------------------------------------- /public/js/app.d61e56cf.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/App.vue?0f16","webpack:///./src/components/Example.vue?5af1","webpack:///./src/App.vue?deeb","webpack:///./src/components/Example.vue?6860","webpack:///./src/components/RankSelectionModal.vue?0423","webpack:///src/components/RankSelectionModal.vue","webpack:///./src/components/RankSelectionModal.vue?8d6e","webpack:///./src/components/RankSelectionModal.vue","webpack:///src/components/Example.vue","webpack:///./src/components/Example.vue?8849","webpack:///./src/components/Example.vue?baf6","webpack:///src/App.vue","webpack:///./src/App.vue?3359","webpack:///./src/App.vue?2667","webpack:///./src/plugins/vuetify.js","webpack:///./src/main.js"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","_vm","this","_h","$createElement","_c","_self","staticClass","attrs","staticStyle","_v","staticRenderFns","model","callback","$$v","panel","expression","ACTION_LIST","method","companies","on","onUpdateRank","scopedSlots","_u","fn","ref","_g","rankForm","headers","loading","item","_s","rank","symbol","toUpperCase","company","formatUSD","marketCap","getCountryFlag","country","proxy","loadData","_e","_t","dialog","close","internalValue","$set","RANK_OP","AMOUNT_LIST","isValid","components","props","type","Array","watch","computed","op","amount","set","$emit","val","methods","component","VBtn","VCard","VCardActions","VCardText","VCardTitle","VDialog","VIcon","VSelect","VSpacer","RankSelectionModal","handler","immediate","created","usd","MILLION","VCol","VContainer","VDataTable","VExpansionPanel","VExpansionPanelContent","VExpansionPanelHeader","VExpansionPanels","VRow","Example","VApp","Vue","use","Vuetify","config","productionTip","vuetify","render","h","App","$mount"],"mappings":"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","file":"js/app.d61e56cf.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"app\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([0,\"chunk-vendors\"]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","export * from \"-!../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=style&index=0&lang=css&\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Example.vue?vue&type=style&index=0&id=6d7466c0&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-app',{staticClass:\"mt-0\",attrs:{\"id\":\"app\"}},[_c('div',{staticStyle:{\"position\":\"absolute\",\"top\":\"-50px\",\"right\":\"0px\",\"width\":\"300px\"}},[_c('img',{attrs:{\"src\":\"https://redislabs.com/wp-content/uploads/2020/12/RedisLabs_Illustration_HomepageHero_v4.svg\"}})]),_c('div',{staticStyle:{\"height\":\"50px\"}}),_c('h1',{staticClass:\"text-center\",staticStyle:{\"color\":\"#444444\"}},[_vm._v(\"Redis Leaderboard Demo\")]),_c('div',{staticStyle:{\"height\":\"50px\"}}),_c('example')],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-container',{staticClass:\"example\"},[_c('v-row',{staticClass:\"mb-5\"},[_c('v-col',{attrs:{\"cols\":\"12\"}},[_c('v-expansion-panels',{attrs:{\"multiple\":\"\"},model:{value:(_vm.panel),callback:function ($$v) {_vm.panel=$$v},expression:\"panel\"}},[_c('v-expansion-panel',[_c('v-expansion-panel-header',[_vm._v(\"How it works?\")]),_c('v-expansion-panel-content',[_c('b',[_vm._v(\"1. How the data is stored:\")]),_c('ol',[_c('li',[_vm._v(\"The company data is stored in a hash like below: \"),_c('pre',[_vm._v(\"HSET \\\"company:AAPL\\\" symbol \\\"AAPL\\\" market_cap \\\"2600000000000\\\" country USA\")])]),_c('li',[_vm._v(\"The Ranks are stored in a ZSET. \"),_c('pre',[_vm._v(\"ZADD companyLeaderboard 2600000000000 company:AAPL\")])])]),_c('br'),_c('b',[_vm._v(\"2. How the data is accessed:\")]),_c('ol',[_c('li',[_vm._v(\"Top 10 companies: \"),_c('pre',[_vm._v(\"ZREVRANGE companyLeaderboard 0 9 WITHSCORES\")])]),_c('li',[_vm._v(\"All companies: \"),_c('pre',[_vm._v(\"ZREVRANGE companyLeaderboard 0 -1 WITHSCORES\")])]),_c('li',[_vm._v(\"Bottom 10 companies: \"),_c('pre',[_vm._v(\"ZRANGE companyLeaderboard 0 9 WITHSCORES\")])]),_c('li',[_vm._v(\"Between rank 10 and 15: \"),_c('pre',[_vm._v(\"ZREVRANGE companyLeaderboard 9 14 WITHSCORES\")])]),_c('li',[_vm._v(\"Show ranks of AAPL, FB and TSLA: \"),_c('pre',[_vm._v(\"ZSCORE companyLeaderBoard company:AAPL company:FB company:TSLA\")])]),_c('li',[_vm._v(\"Adding market cap to companies: \"),_c('pre',[_vm._v(\"ZINCRBY companyLeaderBoard 1000000000 \\\"company:FB\\\"\")])]),_c('li',[_vm._v(\"Reducing market cap to companies: \"),_c('pre',[_vm._v(\"ZINCRBY companyLeaderBoard -1000000000 \\\"company:FB\\\"\")])]),_c('li',[_vm._v(\"Companies over a Trillion: \"),_c('pre',[_vm._v(\"ZCOUNT companyLeaderBoard 1000000000000 +inf\")])]),_c('li',[_vm._v(\"Companies between 500 billion and 1 trillion: \"),_c('pre',[_vm._v(\"ZCOUNT companyLeaderBoard 500000000000 1000000000000\")])])])])],1)],1)],1)],1),_c('v-row',[_c('v-col',{attrs:{\"cols\":\"4\"}},[_c('v-select',{staticStyle:{\"background\":\"#FFF\"},attrs:{\"items\":_vm.ACTION_LIST,\"dense\":\"\",\"outlined\":\"\",\"hide-details\":\"\"},model:{value:(_vm.method),callback:function ($$v) {_vm.method=$$v},expression:\"method\"}})],1),_c('v-col',{staticClass:\"text-right\",attrs:{\"cols\":\"8\"}},[_c('rank-selection-modal',{attrs:{\"companies\":_vm.companies},on:{\"onUpdateRank\":_vm.onUpdateRank},scopedSlots:_vm._u([{key:\"activator\",fn:function(ref){\nvar on = ref.on;\nreturn [_c('v-btn',_vm._g({attrs:{\"color\":\"grey\",\"outlined\":\"\"}},on),[_c('v-icon',{staticClass:\"mr-2\"},[_vm._v(\"mdi-cog-outline\")]),_c('span',{staticStyle:{\"color\":\"#111\",\"text-transform\":\"initial\"}},[_vm._v(\"Update Rank\")])],1)]}}]),model:{value:(_vm.rankForm),callback:function ($$v) {_vm.rankForm=$$v},expression:\"rankForm\"}})],1)],1),_c('v-row',[_c('v-col',{attrs:{\"cols\":\"12\"}},[_c('v-card',{staticClass:\"px-2\",staticStyle:{\"border-right\":\"10px\"}},[_c('v-data-table',{attrs:{\"headers\":_vm.headers,\"items\":_vm.companies,\"loading\":_vm.loading,\"disable-pagination\":true,\"hide-default-footer\":true},scopedSlots:_vm._u([{key:\"item.rank\",fn:function(ref){\nvar item = ref.item;\nreturn [_vm._v(\" \"+_vm._s(item.rank)+\" \")]}},{key:\"item.company\",fn:function(ref){\nvar item = ref.item;\nreturn [_c('div',{staticClass:\"d-flex align-center py-2\"},[_c('div',[_c('img',{staticClass:\"mr-3 my-2\",attrs:{\"src\":(\"https://companiesmarketcap.com//img/company-logos/80/\" + (item.symbol.toUpperCase()) + \".png\"),\"width\":\"40\",\"height\":\"40\"}})]),_c('div',[_c('div',{staticStyle:{\"font-size\":\"1.1rem\"}},[_vm._v(_vm._s(item.company))]),_c('div',{staticClass:\"grey--text\",staticStyle:{\"font-size\":\"0.7rem\"}},[_vm._v(_vm._s(item.symbol.toUpperCase()))])])])]}},{key:\"item.marketCap\",fn:function(ref){\nvar item = ref.item;\nreturn [_c('div',{},[_vm._v(_vm._s(_vm.formatUSD(item.marketCap)))])]}},{key:\"item.country\",fn:function(ref){\nvar item = ref.item;\nreturn [_c('div',{staticClass:\"d-flex align-center\"},[_c('div',[_c('img',{staticClass:\"mr-1\",attrs:{\"src\":_vm.getCountryFlag(item.country),\"width\":\"20\"}})]),_c('div',{},[_vm._v(_vm._s(item.country))])])]}},{key:\"no-data\",fn:function(){return [_c('span',[_vm._v(\" No Results Found. \")])]},proxy:true}])}),(_vm.method === 'paginate')?_c('v-btn',{attrs:{\"color\":\"primary\",\"block\":\"\"},on:{\"click\":_vm.loadData}},[_vm._v(\" Load next 10 \")]):_vm._e()],1)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-dialog',{attrs:{\"transition\":\"dialog-bottom-transition\",\"max-width\":\"400px\"},scopedSlots:_vm._u([{key:\"activator\",fn:function(ref){\nvar on = ref.on;\nvar attrs = ref.attrs;\nreturn [_vm._t(\"activator\",null,null,{ on: on, attrs: attrs })]}}],null,true),model:{value:(_vm.dialog),callback:function ($$v) {_vm.dialog=$$v},expression:\"dialog\"}},[_c('v-card',[_c('v-card-title',[_c('v-spacer'),_c('v-icon',{attrs:{\"aria-label\":\"Close\"},on:{\"click\":_vm.close}},[_vm._v(\" mdi-close \")])],1),_c('v-card-text',[_c('div',{staticClass:\"headline text-center mb-4\"},[_vm._v(\" Select the menus below to update the rank of the companies \")]),_c('v-select',{attrs:{\"items\":_vm.companies,\"item-text\":\"company\",\"item-value\":\"symbol\",\"placeholder\":\"Select a company\",\"dense\":\"\",\"outlined\":\"\"},model:{value:(_vm.internalValue.symbol),callback:function ($$v) {_vm.$set(_vm.internalValue, \"symbol\", $$v)},expression:\"internalValue.symbol\"}}),_c('v-select',{attrs:{\"items\":_vm.RANK_OP,\"placeholder\":\"Add or Subtract\",\"dense\":\"\",\"outlined\":\"\"},model:{value:(_vm.internalValue.op),callback:function ($$v) {_vm.$set(_vm.internalValue, \"op\", $$v)},expression:\"internalValue.op\"}}),_c('v-select',{attrs:{\"items\":_vm.AMOUNT_LIST,\"placeholder\":\"Select Amount\",\"dense\":\"\",\"outlined\":\"\"},model:{value:(_vm.internalValue.amount),callback:function ($$v) {_vm.$set(_vm.internalValue, \"amount\", $$v)},expression:\"internalValue.amount\"}})],1),_c('v-card-actions',[_c('v-spacer'),_c('v-btn',{staticClass:\"mb-4\",attrs:{\"color\":\"primary\",\"disabled\":!_vm.isValid},on:{\"click\":_vm.onUpdateRank}},[_vm._v(\" Update \")])],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RankSelectionModal.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RankSelectionModal.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./RankSelectionModal.vue?vue&type=template&id=67081f4c&\"\nimport script from \"./RankSelectionModal.vue?vue&type=script&lang=js&\"\nexport * from \"./RankSelectionModal.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VCardActions } from 'vuetify/lib/components/VCard';\nimport { VCardText } from 'vuetify/lib/components/VCard';\nimport { VCardTitle } from 'vuetify/lib/components/VCard';\nimport { VDialog } from 'vuetify/lib/components/VDialog';\nimport { VIcon } from 'vuetify/lib/components/VIcon';\nimport { VSelect } from 'vuetify/lib/components/VSelect';\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\ninstallComponents(component, {VBtn,VCard,VCardActions,VCardText,VCardTitle,VDialog,VIcon,VSelect,VSpacer})\n","\n\n\n\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Example.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Example.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./Example.vue?vue&type=template&id=6d7466c0&scoped=true&\"\nimport script from \"./Example.vue?vue&type=script&lang=js&\"\nexport * from \"./Example.vue?vue&type=script&lang=js&\"\nimport style0 from \"./Example.vue?vue&type=style&index=0&id=6d7466c0&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"6d7466c0\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VCol } from 'vuetify/lib/components/VGrid';\nimport { VContainer } from 'vuetify/lib/components/VGrid';\nimport { VDataTable } from 'vuetify/lib/components/VDataTable';\nimport { VExpansionPanel } from 'vuetify/lib/components/VExpansionPanel';\nimport { VExpansionPanelContent } from 'vuetify/lib/components/VExpansionPanel';\nimport { VExpansionPanelHeader } from 'vuetify/lib/components/VExpansionPanel';\nimport { VExpansionPanels } from 'vuetify/lib/components/VExpansionPanel';\nimport { VIcon } from 'vuetify/lib/components/VIcon';\nimport { VRow } from 'vuetify/lib/components/VGrid';\nimport { VSelect } from 'vuetify/lib/components/VSelect';\ninstallComponents(component, {VBtn,VCard,VCol,VContainer,VDataTable,VExpansionPanel,VExpansionPanelContent,VExpansionPanelHeader,VExpansionPanels,VIcon,VRow,VSelect})\n","\n\n\n\n\n","import mod from \"-!../node_modules/cache-loader/dist/cjs.js??ref--12-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../node_modules/cache-loader/dist/cjs.js??ref--12-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./App.vue?vue&type=template&id=70837e76&\"\nimport script from \"./App.vue?vue&type=script&lang=js&\"\nexport * from \"./App.vue?vue&type=script&lang=js&\"\nimport style0 from \"./App.vue?vue&type=style&index=0&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VApp } from 'vuetify/lib/components/VApp';\ninstallComponents(component, {VApp})\n","import Vue from 'vue';\nimport Vuetify from 'vuetify/lib/framework';\n\nVue.use(Vuetify);\n\nexport default new Vuetify({\n});\n","import Vue from 'vue'\nimport App from './App.vue'\nimport vuetify from './plugins/vuetify';\n\nVue.config.productionTip = false\n\nnew Vue({\n vuetify,\n render: h => h(App)\n}).$mount('#app')\n"],"sourceRoot":""} --------------------------------------------------------------------------------