Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hkts #3

Draft
wants to merge 39 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2decae5
Started implementing HKTs
arnasbr Sep 18, 2023
8375696
Small improvements
arnasbr Sep 19, 2023
01c1dbe
Changed CliArgs inputFile to FilePath instead of String
arnasbr Sep 19, 2023
866bbc4
Refactored some code, moved unsafeRunSync to the very end of the program
arnasbr Sep 19, 2023
400089e
Some code refactoring, a little bit of parallelism
arnasbr Sep 20, 2023
3ae5850
Implemented api token input
arnasbr Sep 20, 2023
8c234a1
Changed Async to Sync in openInBrowser
arnasbr Sep 20, 2023
24ad063
Update .gitignore
arnasbr Sep 21, 2023
66f511e
Update .gitignore
arnasbr Sep 21, 2023
e258075
Cleaned up import statements
arnasbr Sep 22, 2023
b87f60c
Moved to stable sttp version
arnasbr Sep 22, 2023
eead56c
Implemented support for Futures
arnasbr Sep 25, 2023
63a15b9
Fixed error handling
arnasbr Sep 26, 2023
27686ca
Added Parsing and FeatureCreation tests
arnasbr Sep 26, 2023
4221fbf
Removed ability to open image in browser
arnasbr Sep 26, 2023
39dd332
Reformated some code, added more tests
arnasbr Sep 26, 2023
ec3cb09
Updated imports
arnasbr Sep 26, 2023
ae0784f
Created integration test
arnasbr Sep 26, 2023
fbdfd6e
Created github action for integration testing and linting
arnasbr Sep 26, 2023
1ba31fe
Updated integration test
arnasbr Sep 26, 2023
8408ef6
Updated integration test
arnasbr Sep 26, 2023
cce900d
Debugging ci cd
arnasbr Sep 26, 2023
4dde8e1
Debugging ci cd
arnasbr Sep 26, 2023
d47f9cc
Debugging ci cd
arnasbr Sep 26, 2023
2823ad4
Debugging ci cd
arnasbr Sep 26, 2023
de55d10
Changed integration test to only check for file existance
arnasbr Sep 26, 2023
671dbae
Update integration test
arnasbr Sep 26, 2023
56da5c0
Update integration test
arnasbr Sep 26, 2023
b6d9b0b
Update integration test
arnasbr Sep 26, 2023
b900f7a
Update integration test
arnasbr Sep 26, 2023
5836d31
Finalizing integration test
arnasbr Sep 26, 2023
073a506
Deleted unnecessary file
arnasbr Sep 26, 2023
82cdc36
Implemented support for docker
arnasbr Sep 27, 2023
5a41a96
Fixed outputDir
arnasbr Sep 27, 2023
45ec47c
Cleaned up build.sbt
arnasbr Sep 29, 2023
44eb4c9
Cleaned up UnsafeRun.scala
arnasbr Sep 29, 2023
b15e3b9
Replaced Java URI with sttp Uri
arnasbr Oct 2, 2023
0c47c13
Removed hardcoded mapbox api token from integration test
arnasbr Oct 2, 2023
6e013e5
Improved intergrationTest.sh
arnasbr Oct 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build

on:
push:
branches: [ master ]

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11

- name: Login to DockerHub
run: docker login -u '${{secrets.DOCKER_HUB_USER}}' -p '${{secrets.DOCKER_HUB_PASSWORD}}'

- name: Build docker image
run: sbt docker:publish
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set execute permissions on script
run: chmod +x ./integrationTest.sh
- name: Run integration test
env:
MAPBOX_API_TOKEN: ${{ secrets.MAPBOX_API_TOKEN }}
run: ./integrationTest.sh "$MAPBOX_API_TOKEN"
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Formatting
run: sbt scalafmtSbtCheck scalafmtCheck test:scalafmtCheck
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ build/
.idea
.bsp

outputDir

logs/

# metals lsp files
.bloop
.metals
metals.sbt
44 changes: 29 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,61 @@ Create an image of a map with given point coordinates.
You need to have [SBT](https://www.scala-sbt.org/download.html) installed on your machine to run this project.

## Installation

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make readme a little bit more readable


To install GeoJson Formatter, follow these steps:

Windows/Mac/Linux:

```bash
$ git clone https://github.com/arnasbr/geopoint-visualizer.git
$ cd geopoint-visualizer
```

## Api Token

Create an account in https://account.mapbox.com/

Use your `Default public token` (or create a new one)

## Usage
Start sbt, pass in input. `run plot --help` for help

```
Usage: geopoint-visualizer plot [--swap] [--download] [--browser] [--img_size <integer>] [--input <string>]
Usage: geopoint-visualizer plot --token <string> [--swap] [--future] [--img_size <integer>] [--input <string>]

Plots given points on a map

Options and flags:
--help
Display this help text.
--token <string>
Mapbox api token
--swap
Flag to indicate if latitude and longitude should be swapped (default - false)
--download
Flag to indicate if image should be downloaded to outputDir
--browser
Flag to indicate if image should be opened in browser
Flag to indicate if latitude and longitude should be swapped
--future
Flag to indicate if app should be run using Futures instead of IO (cats effect)
--img_size <integer>
Image size 1-1280 (default - 1000)
--input <string>
Input file path (default - inputDir/input.json)
```

If neither --download nor --browser flags are chosen, by default only --download will happen
#### Examples
```bash
$ sbt "run plot --token <your_api_token> --swap --img_size 1000 --input inputDir/input.json"

#### Example
$ sbt "run plot --token <your_api_token> --swap --future" //use default image size and input file and use Future
```

#### Running with Docker
```bash
$ sbt
sbt: geopoint-visualizer> run plot --swap --download --browser --img_size 1000 --input "inputDir/input.json"
$ docker run\

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you must mention all optional flags and default values

--user $(id -u):$(id -g) \
-v ./inputDir:/app/inputDir \
-v ./outputDir:/app/outputDir \
-it arnasbr/geopoint-visualizer:latest \
plot \
--token <your_api_token> \
--swap
```

When using a different input file than the default inputDir/input.json, don't forget to change the -v volume and use the --input tag.

## Result

![image](https://github.com/arnasbr/geopoint-visualizer/assets/140691866/dd311615-b5e2-4135-b26b-3f69e4e73a20)
Expand Down
26 changes: 23 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
ThisBuild / version := "0.1.0-SNAPSHOT"
import com.typesafe.sbt.packager.docker.DockerPermissionStrategy

enablePlugins(DockerPlugin, JavaAppPackaging, GitVersioning)

name := "geopoint-visualizer"
organization := "igeolise"
version := git.gitHeadCommit.value.getOrElse("0.1").take(5)

Docker / packageName := packageName.value
Docker / version := version.value
dockerBaseImage := "openjdk:11"
arnasbr marked this conversation as resolved.
Show resolved Hide resolved
dockerExposedVolumes := Seq(
"/app/inputDir",
"/app/outputDir"
)
Docker / defaultLinuxInstallLocation := "/app"
dockerRepository := Some("arnasbr")
dockerUpdateLatest := true
dockerPermissionStrategy := DockerPermissionStrategy.MultiStage

ThisBuild / scalaVersion := "2.13.11"

Expand All @@ -13,6 +31,8 @@ libraryDependencies ++= Seq(
"io.circe" %% "circe-parser" % circeVersion,
"io.circe" %% "circe-generic" % circeVersion,
"com.monovore" %% "decline" % "2.4.1",
"com.softwaremill.sttp.client4" %% "core" % "4.0.0-M4",
"org.typelevel" %% "cats-effect" % "3.5.1"
"com.softwaremill.sttp.client3" %% "core" % "3.9.0",
"com.softwaremill.sttp.client3" %% "cats" % "3.9.0",
"org.typelevel" %% "cats-effect" % "3.5.1",
"org.scalatest" %% "scalatest" % "3.2.15" % Test
)
28 changes: 28 additions & 0 deletions integrationTest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# Check if any arguments are passed
if [ "$#" -ne 1 ]; then
echo "Usage: ./integrationTest.sh <MAPBOX_API_TOKEN>"
echo "You must provide the Mapbox API token as an argument."
exit 1
fi

# Check if outputDir/output.png exists and delete it
if test -f "outputDir/output.png"; then
echo "Deleting existing outputDir/output.png."
rm -f "outputDir/output.png"
fi

token=$1

# Run the Scala app with sbt
sbt "run plot --token $token --swap --input integrationTestData/integrationTestInput.json"

# Check if the output.png file exists
if test -f "outputDir/output.png"; then
echo "outputDir/output.png exists."
exit 0
else
echo "outputDir/output.png does not exist."
exit 1
fi
8 changes: 8 additions & 0 deletions integrationTestData/integrationTestInput.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
[
[
51.499619505045594,
-0.12919985466434053
]
]
]
Empty file added outputDir/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0")
49 changes: 0 additions & 49 deletions src/main/scala/AppRunner.scala

This file was deleted.

35 changes: 18 additions & 17 deletions src/main/scala/Cli.scala
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import Models.CliArgs
import Models.{CliArgs, FilePath}
import cats.implicits.catsSyntaxTuple5Semigroupal
import com.monovore.decline._

object Cli {
private val apiToken: Opts[String] =
Opts
.option[String](
"token",
help = "Mapbox api token"
)

private val swapFlag: Opts[Boolean] = Opts
.flag(
"swap",
help =
"Flag to indicate if latitude and longitude should be swapped (default - false)"
help = "Flag to indicate if latitude and longitude should be swapped"
)
.orFalse

private val downloadFlag: Opts[Boolean] = Opts
private val futureFlag: Opts[Boolean] = Opts
.flag(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's do with zio too. Instead of future flag use enum

"download",
help = "Flag to indicate if image should be downloaded to outputDir"
)
.orFalse

private val browserFlag: Opts[Boolean] = Opts
.flag(
"browser",
help = "Flag to indicate if image should be opened in browser"
"future",
help =
"Flag to indicate if app should be run using Futures instead of IO (cats effect)"
)
.orFalse

Expand All @@ -30,20 +30,21 @@ object Cli {
.option[Int]("img_size", help = "Image size 1-1280 (default - 1000)")
.withDefault(1000)

private val inputFile: Opts[String] =
private val inputFile: Opts[FilePath] =
Opts

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

support multiple input files. So you can pass a dir instead and then create image per file

.option[String](
"input",
help = "Input file path (default - inputDir/input.json)"
)
.withDefault("inputDir/input.json")
.map(FilePath)
.withDefault(FilePath("inputDir/input.json"))

val command: Opts[CliArgs] = Opts.subcommand(
Command(name = "plot", header = "Plots given points on a map")(
(
apiToken,
swapFlag,
downloadFlag,
browserFlag,
futureFlag,
imageSize,
inputFile
).mapN(CliArgs)
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/FeatureCreation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object FeatureCreation {
featureCollection.printWith(Printer.noSpaces)
}

private def createFeatures(
def createFeatures(
inputCoordinatesListOpt: Option[List[CoordinatesList]],
colors: LazyList[Color]
): List[Json] = {
Expand Down
20 changes: 20 additions & 0 deletions src/main/scala/HelperUtils.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import FeatureCreation.createFeatureCollection
import Parsing.parseInputCoordinates
import sttp.client3.UriContext
import scala.io.BufferedSource
import sttp.model.Uri

object HelperUtils {
def generateStaticImageUri(
fileSource: BufferedSource,
swapFlag: Boolean,
colors: LazyList[Color],
imageSize: Int,
apiToken: String
): Uri = {
val inputCoordinates = parseInputCoordinates(fileSource, swapFlag)
val featureCollection = createFeatureCollection(inputCoordinates, colors)

uri"https://api.mapbox.com/styles/v1/mapbox/dark-v11/static/geojson($featureCollection)/auto/${imageSize}x$imageSize?access_token=$apiToken"
}
}
Loading
Loading