text:
"""
    Path()
    Path(path::AbstractPath)
    Path(path::Tuple)
    Path(path::AbstractString)

Responsible for creating the appropriate platform specific path
(e.g., `PosixPath` and `WindowsPath` for Unix and Windows systems respectively)
"""
Path() = @static Sys.isunix() ? PosixPath() : WindowsPath()
Path(path::AbstractPath) = path
Path(pieces::Tuple{Vararg{String}}) =
    @static Sys.isunix() ? PosixPath(pieces) : WindowsPath(pieces)

# May want to support using the registry for other constructors as well
function Path(str::AbstractString; debug=false)
    types = filter(t -> ispathtype(t, str), PATH_TYPES)

    if length(types) > 1
        @debug(
            string(
                "Found multiple path types that match the string specified ($types). ",
                "Please use a specific constructor if $(first(types)) is not the correct type."
            )
        )
    end

    return first(types)(str)
end

"""
    @p_str -> Path

Constructs a `Path` (platform specific subtype of `AbstractPath`), such as
`p"~/.juliarc.jl"`.
"""
macro p_str(path)
    Path(path)
end

cwd() = Path(pwd())
home() = Path(homedir())

anchor(path::AbstractPath) = drive(path) * root(path)

"""
    @__PATH__ -> AbstractPath

@__PATH__ expands to a path with the directory part of the absolute path
of the file containing the macro. Returns an empty Path if run from a REPL or
if evaluated by julia -e <expr>.
"""
macro __PATH__()
    p = Path(dirname(string(__source__.file)))
    return p === nothing ? :(Path()) : :($p)
end

"""
    @__FILEPATH__ -> AbstractPath

@__FILEPATH__ expands to a path with the absolute file path of the file
containing the macro. Returns an empty Path if run from a REPL or if
evaluated by julia -e <expr>.
"""
macro __FILEPATH__()
    p = Path(string(__source__.file))
    return p === nothing ? :(Path()) : :($p)
end

"""
    @LOCAL(filespec)

Construct an absolute path to `filespec` relative to the source file
containing the macro call.
"""
macro LOCAL(filespec)
    p = join(Path(dirname(string(__source__.file))), Path(filespec))
    return :($p)
end

#=
Path Modifiers
===============================================
The following are methods for working with and extracting
path components
=#
"""
    hasparent(path::AbstractPath) -> Bool

Returns whether there is a parent directory component to the supplied path.
"""
hasparent(path::AbstractPath) = length(parts(path)) > 1

"""
    parent{T<:AbstractPath}(path::T) -> T

Returns the parent of the supplied path.

# Example
```
julia> parent(p"~/.julia/v0.6/REQUIRE")
p"~/.julia/v0.6"
```

# Throws
* `ErrorException`: if `path` doesn't have a parent
"""
Base.parent(path::AbstractPath) = parents(path)[end]

"""
    parents{T<:AbstractPath}(path::T) -> Array{T}

# Example
```
julia> parents(p"~/.julia/v0.6/REQUIRE")
3-element Array{FilePathsBase.PosixPath,1}:
 p"~"
 p"~/.julia"
 p"~/.julia/v0.6"
 ```

# Throws
* `ErrorException`: if `path` doesn't have a parent
"""
function parents(path::T) where {T <: AbstractPath}
    if hasparent(path)
        return map(1:length(parts(path))-1) do i
            T(parts(path)[1:i])
        end
    else
        error("$path has no parents")
    end
end

"""
  *(a::T, b::Union{T, AbstractString, AbstractChar}...) where {T <: AbstractPath} -> T

Concatenate paths, strings and/or characters, producing a new path.
This is equivalent to concatenating the string representations of paths and other strings
and then constructing a new path.

# Example

julia> p"foo" * "bar"
p"foobar"
"""
function Base.:(*)(a::T, b::Union{T, AbstractString, AbstractChar}...) where T <: AbstractPath
    T(*(string(a), string.(b)...))
end

"""
  /(a::AbstractPath, b::Union{AbstractPath, AbstractString}...) -> AbstractPath

Join the path components into a new fulll path, equivalent to calling `joinpath`

# Example

julia> p"foo" / "bar"
p"foo/bar"

julia> p"foo" / "bar" / "baz"
p"foo/bar/baz"
"""
function Base.:(/)(root::AbstractPath, pieces::Union{AbstractPath, AbstractString}...)
    join(root, pieces...)
end

"""
    join(root::AbstractPath, pieces::Union{AbstractPath, AbstractString}...) -> AbstractPath

Joins path components into a full path.

# Example
```
julia> join(p"~/.julia/v0.6", "REQUIRE")
p"~/.julia/v0.6/REQUIRE"
```
"""
function Base.join(root::AbstractPath, pieces::Union{AbstractPath, AbstractString}...)
    all_parts = String[]
    push!(all_parts, parts(root)...)

    for p in map(Path, pieces)
        push!(all_parts, parts(p)...)
    end

    return Path(tuple(all_parts...))
end

function Base.joinpath(root::AbstractPath, pieces::Union{AbstractPath, AbstractString}...)
    return join(root, pieces...)
end

Base.basename(path::AbstractPath) = parts(path)[end]

"""
    filename(path::AbstractPath) -> AbstractString

Extracts the `basename` without any extensions.

# Example
```
julia> filename(p"~/repos/FilePathsBase.jl/src/FilePathsBase.jl")
"FilePathsBase"
```
"""
function filename(path::AbstractPath)
    name = basename(path)
    return split(name, '.')[1]
end

"""
    extension(path::AbstractPath) -> AbstractString

Extracts the last extension from a filename if there any, otherwise it returns an empty string.

# Example
```
julia> extension(p"~/repos/FilePathsBase.jl/src/FilePathsBase.jl")
"jl"
```
"""
function extension(path::AbstractPath)
    name = basename(path)

    tokenized = split(name, '.')
    if length(tokenized) > 1
        return tokenized[end]
    else
        return ""
    end
end

"""
    extensions(path::AbstractPath) -> AbstractString

Extracts all extensions from a filename if there any, otherwise it returns an empty string.

# Example
```
julia> extensions(p"~/repos/FilePathsBase.jl/src/FilePathsBase.jl.bak")
2-element Array{SubString{String},1}:
 "jl"
 "bak"
```
"""
function extensions(path::AbstractPath)
    name = basename(path)

    tokenized = split(name, '.')
    if length(tokenized) > 1
        return tokenized[2:end]
    else
        return []
    end
end

"""
    isempty(path::AbstractPath) -> Bool

Returns whether or not a path is empty.

NOTE: Empty paths are usually only created by `Path()`, as `p""` and `Path("")` will
default to using the current directory (or `p"."`).
"""
Base.isempty(path::AbstractPath) = isempty(parts(path))

"""
    exists(path::AbstractPath) -> Bool

Returns whether the path actually exists on the system.
"""
exists(path::AbstractPath) = ispath(string(path))

"""
    real(path::AbstractPath) -> AbstractPath

Canonicalizes a path by expanding symlinks and removing "." and ".." entries.
"""
Base.real(path::AbstractPath) = Path(realpath(string(path)))

"""
    norm(path::AbstractPath) -> AbstractPath

Normalizes a path by removing "." and ".." entries.
"""
function LinearAlgebra.norm(path::T) where {T <: AbstractPath}
    p = parts(path)
    result = String[]
    rem = length(p)
    count = 0
    del = 0

    while count < length(p)
        str = p[end-count]

        if str == ".."
            del += 1
        elseif str != "."
            if del == 0
                push!(result, str)
            else
                del -= 1
            end
        end

        rem -= 1
        count += 1
    end

    return T(tuple(fill("..", del)..., reverse(result)...))
end

"""
    abs(path::AbstractPath) -> AbstractPath

Creates an absolute path by adding the current working directory if necessary.
"""
function Base.abs(path::AbstractPath)
    result = expanduser(path)

    if isabs(result)
        return norm(result)
    else
        return norm(join(cwd(), result))
    end
end

"""
    relative{T<:AbstractPath}(path::T, start::T=T("."))

Creates a relative path from either the current directory or an arbitrary start directory.
"""
function relative(path::T, start::T=T(".")) where {T <: AbstractPath}
    curdir = "."
    pardir = ".."

    p = parts(abs(path))
    s = parts(abs(start))

    p == s && return T(curdir)

    i = 0
    while i < min(length(p), length(s))
        i += 1
        @static if Sys.iswindows()
            if lowercase(p[i]) != lowercase(s[i])
                i -= 1
                break
            end
        else
            if p[i] != s[i]
                i -= 1
                break
            end
        end
    end

    pathpart = p[i+1:findlast(x -> !isempty(x), p)]
    prefix_num = findlast(x -> !isempty(x), s) - i - 1
    if prefix_num >= 0
        relpath_ = isempty(pathpart) ?
            tuple(fill(pardir, prefix_num + 1)...) :
            tuple(fill(pardir, prefix_num + 1)..., pathpart...)
    else
        relpath_ = pathpart
    end
    return isempty(relpath_) ? T(curdir) : T(relpath_)
end

#=
The following a descriptive methods for paths
built around stat
=#
Base.stat(path::AbstractPath) = Status(stat(string(path)))
Base.lstat(path::AbstractPath) = Status(lstat(string(path)))

"""
    mode(path::AbstractPath) -> Mode

Returns the `Mode` for the specified path.

# Example
```
julia> mode(p"src/FilePathsBase.jl")
-rw-r--r--
```
"""
mode(path::AbstractPath) = stat(path).mode
Base.size(path::AbstractPath) = stat(path).size

"""
    modified(path::AbstractPath) -> DateTime

Returns the last modified date for the `path`.

# Example
```
julia> modified(p"src/FilePathsBase.jl")
2017-06-20T04:01:09
```
"""
modified(path::AbstractPath) = stat(path).mtime

"""
    created(path::AbstractPath) -> DateTime

Returns the creation date for the `path`.

# Example
```
julia> created(p"src/FilePathsBase.jl")
2017-06-20T04:01:09
```
"""
created(path::AbstractPath) = stat(path).ctime
Base.isdir(path::AbstractPath) = isdir(mode(path))
Base.isfile(path::AbstractPath) = isfile(mode(path))
Base.islink(path::AbstractPath) = islink(lstat(path).mode)
Base.issocket(path::AbstractPath) = issocket(mode(path))
Base.isfifo(path::AbstractPath) = issocket(mode(path))
Base.ischardev(path::AbstractPath) = ischardev(mode(path))
Base.isblockdev(path::AbstractPath) = isblockdev(mode(path))

"""
    isexecutable(path::AbstractPath) -> Bool

Returns whether the `path` is executable for the current user.
"""
function isexecutable(path::AbstractPath)
    s = stat(path)
    usr = User()

    return isexecutable(s.mode, :ALL) || isexecutable(s.mode, :OTHER) ||
        ( usr.uid == s.user.uid && isexecutable(s.mode, :USER) ) ||
        ( usr.gid == s.group.gid && isexecutable(s.mode, :GROUP) )
end

"""
    iswritable(path::AbstractPath) -> Bool

Returns whether the `path` is writable for the current user.
"""
function Base.iswritable(path::AbstractPath)
    s = stat(path)
    usr = User()

    return iswritable(s.mode, :ALL) || iswritable(s.mode, :OTHER) ||
        ( usr.uid == s.user.uid && iswritable(s.mode, :USER) ) ||
        ( usr.gid == s.group.gid && iswritable(s.mode, :GROUP) )
end

"""
    isreadable(path::AbstractPath) -> Bool

Returns whether the `path` is readable for the current user.
"""
function Base.isreadable(path::AbstractPath)
    s = stat(path)
    usr = User()

    return isreadable(s.mode, :ALL) || isreadable(s.mode, :OTHER) ||
        ( usr.uid == s.user.uid && isreadable(s.mode, :USER) ) ||
        ( usr.gid == s.group.gid && isreadable(s.mode, :GROUP) )
end

function Base.ismount(path::AbstractPath)
    isdir(path) || return false
    s1 = lstat(path)
    # Symbolic links cannot be mount points
    islink(s1) && return false
    s2 = lstat(parent(path))
    # If a directory and its parent are on different devices,  then the
    # directory must be a mount point
    (s1.device != s2.device) && return true
    (s1.inode == s2.inode) && return true
    false
end

#=
Path Operations
===============================================
The following are methods for actually manipulating the
filesystem.

NOTE: Currently, we are just wrapping base julia functions,
but in the future we'll likely be handling platform specific
code in the implementation instances.

TODO: Document these once we're comfortable with them.
=#

Base.cd(path::AbstractPath) = cd(string(path))
function Base.cd(fn::Function, dir::AbstractPath)
    old = cwd()
    try
        cd(dir)
        fn()
   finally
        cd(old)
    end
end

function Base.mkdir(path::AbstractPath; mode=0o777, recursive=false, exist_ok=false)
    if exists(path)
        !exist_ok && error("$path already exists.")
    else
        if hasparent(path) && !exists(parent(path))
			if recursive
				mkdir(parent(path); mode=mode, recursive=recursive, exist_ok=exist_ok)
			else
				error(
					"The parent of $path does not exist. " *
					"Pass recursive=true to create it."
				)
			end
        end

		mkdir(string(path), mode=mode)
    end
end

function Base.symlink(src::AbstractPath, dest::AbstractPath; exist_ok=false, overwrite=false)
    if exists(src)
        if exists(dest) && exist_ok && overwrite
            remove(dest, recursive=true)
        end

        if !exists(dest)
            symlink(string(src), string(dest))
        elseif !exist_ok
            error("$dest already exists.")
        end
    else
        error("$src is not a valid path")
    end
end

function Base.copy(src::AbstractPath, dest::AbstractPath; recursive=false, exist_ok=false, overwrite=false, symlinks=false)
    if exists(src)
        if exists(dest) && exist_ok && overwrite
            remove(dest, recursive=true)
        end

        if !exists(dest)
            if hasparent(dest) && recursive
                mkdir(parent(dest); recursive=recursive, exist_ok=true)
            end

            cp(src, dest; follow_symlinks=symlinks)
        elseif !exist_ok
            error("$dest already exists.")
        end
    else
        error("$src is not a valid path")
    end
end

function move(src::AbstractPath, dest::AbstractPath; recursive=false, exist_ok=false, overwrite=false)
    if exists(src)
        if exists(dest) && exist_ok && overwrite
            remove(dest, recursive=true)
        end

        if !exists(dest)
            # If the destination is has missing parents
            # and parents is true then we'll create the necessary parent
            # directories.
            if hasparent(dest) && recursive
                mkdir(parent(dest); recursive=recursive, exist_ok=true)
            end

            mv(string(src), string(dest))
        elseif !exist_ok
            error("$dest already exists.")
        end
    else
        error("$src is not a valid path")
    end
end

function Base.cp(src::AbstractPath, dest::AbstractPath; force::Bool=false, follow_symlinks::Bool=false)
    cp(string(src), string(dest); force=force, follow_symlinks=follow_symlinks)
end

remove(path::AbstractPath; recursive=false) = rm(string(path); recursive=recursive)
Base.touch(path::AbstractPath) = touch(string(path))

tmpname() = Path(tempname())
tmpdir() = Path(tempdir())

function mktmp(parent::AbstractPath=Path(tempdir()))
    path, io = mktemp(string(parent))
    return Path(path), io
end

mktmpdir(parent::AbstractPath=tmpdir()) = Path(mktempdir(string(parent)))

function mktmp(fn::Function, parent=tmpdir())
    (tmp_path, tmp_io) = mktmp(parent)
    try
        fn(tmp_path, tmp_io)
    finally
        close(tmp_io)
        remove(tmp_path)
    end
end

function mktmpdir(fn::Function, parent=tmpdir())
    tmpdir = mktmpdir(parent)
    try
        fn(tmpdir)
    finally
        remove(tmpdir, recursive=true)
    end
end

"""
    chown(path::AbstractPath, user::AbstractString, group::AbstractString; recursive=false)

Change the `user` and `group` of the `path`.
"""
function Base.chown(path::AbstractPath, user::AbstractString, group::AbstractString; recursive=false)
    @static if Sys.isunix()
        chown_cmd = String["chown"]
        if recursive
            push!(chown_cmd, "-R")
        end
        append!(chown_cmd, String["$(user):$(group)", string(path)])

        run(Cmd(chown_cmd))
    else
        error("chown is currently not supported on windows.")
    end
end

"""
    chmod(path::AbstractPath, mode::Mode; recursive=false)
    chmod(path::AbstractPath, mode::Integer; recursive=false)
    chmod(path::AbstractPath, user::UIn8=0o0, group::UInt8=0o0, other::UInt8=0o0; recursive=false)
    chmod(path::AbstractPath, symbolic_mode::AbstractString; recursive=false)

Provides various methods for changing the `mode` of a `path`.

# Examples
```
julia> touch(p"newfile")
Base.Filesystem.File(false, RawFD(-1))

julia> mode(p"newfile")
-rw-r--r--

julia> chmod(p"newfile", 0o755)

julia> mode(p"newfile")
-rwxr-xr-x

julia> chmod(p"newfile", "-x")

julia> mode(p"newfile")
-rw-r--r--

julia> chmod(p"newfile", user=(READ+WRITE+EXEC), group=(READ+EXEC), other=READ)

julia> mode(p"newfile")
-rwxr-xr--

julia> chmod(p"newfile", mode(p"src/FilePathsBase.jl"))

julia> mode(p"newfile")
-rw-r--r--
```
"""
function Base.chmod(path::AbstractPath, mode::Mode; recursive=false)
    chmod_path = string(path)
    chmod_mode = raw(mode)

    if isdir(path) && recursive
        for p in readdir(path)
            chmod(chmod_path, chmod_mode; recursive=recursive)
        end
    end

    chmod(chmod_path, chmod_mode)
end

function Base.chmod(path::AbstractPath, mode::Integer; recursive=false)
    chmod(path, Mode(mode); recursive=recursive)
end

function Base.chmod(path::AbstractPath; user::UInt8=0o0, group::UInt8=0o0, other::UInt8=0o0, recursive=false)
    chmod(path, Mode(user=user, group=group, other=other); recursive=recursive)
end

function Base.chmod(path::AbstractPath, symbolic_mode::AbstractString; recursive=false)
    who_char = ['u', 'g', 'o']
    who_actual = [:USER, :GROUP, :OTHER]
    act_char = ['+', '-', '=']
    perm_char = ['r', 'w', 'x']
    perm_actual = [READ, WRITE, EXEC]
    unsupported_perm_char = ['s', 't', 'X', 'u', 'g', 'o']

    tokenized = split(symbolic_mode, act_char)
    if length(tokenized) != 2
        error("Invalid symbolic string expected format <who><action><perm>.")
    end

    who_raw = tokenized[1]
    perm_raw = tokenized[2]

    who = [:ALL]
    perm = 0o0

    for i in 1:3
        if who_char[i] in who_raw
            push!(who, who_actual[i])
        end
    end

    for i in 1:3
        if perm_char[i] in perm_raw
            perm += perm_actual[i]
        end
    end

    for x in unsupported_perm_char
        if x in perm_raw
            error("$x is currently an unsupported permission char for symbolic modes.")
        end
    end

    m = mode(path)
    new_m = Mode(perm, who...)

    if '+' in symbolic_mode
        chmod(path, m + new_m; recursive=recursive)
    elseif '-' in symbolic_mode
        chmod(path, m - new_m; recursive=recursive)
    elseif '=' in symbolic_mode
        chmod(path, new_m; recursive=recursive)
    else
        error("No valid action found in symbolic mode string.")
    end
end

Base.open(path::AbstractPath, args...) = open(string(path), args...)
function Base.open(f::Function, path::AbstractPath, args...; kwargs...)
    open(f, string(path), args...; kwargs...)
end

Base.read(path::AbstractPath) = read(string(path), String)

function Base.write(path::AbstractPath, content::AbstractString, mode="w")
    open(path, mode) do f
        write(f, content)
    end
end

Base.readlink(path::AbstractPath) = Path(readlink(string(path)))
Base.readdir(path::AbstractPath) = map(Path, readdir(string(path)))

function Base.download(src::AbstractString, dest::AbstractPath, overwrite::Bool=false)
    if !exists(dest) || overwrite
        download(src, string(dest))
    end
    return dest
end


text:
function update_derivs_pos!(state::Vector{Float64}, derivs::Vector{Float64} )
 # Input: state = [x,y,vx,vy], a vector of two 2-d positions and velocities for a test particle
 # Output: The derivatives of the position are updated in the preallocated array derivs.
  @assert length(state) == 4
  @assert length(derivs) == 4
  v_x = state[3]
  v_y = state[4]
  derivs[1] = v_x
  derivs[2] = v_y
  return derivs;
end

function update_derivs_vel!(state::Vector{Float64}, derivs::Vector{Float64} )
  # Input: state = [x,y,vx,vy], a vector of two 2-d positions and velocities for a test particle
  # Output: The derivatives of the velocity are updated in the preallocated array derivs.
  @assert length(state) == 4
  @assert length(derivs) == 4
  GM = 1.0
  r_x = state[1]
  r_y = state[2]
  r2 = r_x*r_x+r_y*r_y
  a = -GM/r2
  r = sqrt(r2)
  a_x = a * r_x/r
  a_y = a * r_y/r
  derivs[3] = a_x
  derivs[4] = a_y
  return derivs;
end

function update_derivs!(state::Vector{Float64}, derivs::Vector{Float64} )
  # Input: state = [x,y,vx,vy], a vector of two 2-d positions and velocities for a test particle
  # Output: The derivatives are updated in the preallocated array derivs.
  update_derivs_vel!(state,derivs)
  update_derivs_pos!(state,derivs)
  return derivs
end

function advance_leapfrog!(state::Vector{Float64},derivs::Vector{Float64}, dt::Float64; derivs_current::Bool = false)
  # Input/Output: state = array of two 2-d positions and velocities for a test particle
  # Temporary space: The derivatives are updated in the preallocated array derivs.
  # Input: dt is the fixed time step
  # Optional param: derivs_current: whether need to calculate derivatives at beginning
  @assert length(state) == length(derivs)

  if !derivs_current
    update_derivs_pos!(state,derivs);
  end
  state[1] += 0.5*dt*derivs[1]
  state[2] += 0.5*dt*derivs[2]
  update_derivs_vel!(state,derivs);
  state[3] += dt*derivs[3]
  state[4] += dt*derivs[4]
  update_derivs_pos!(state,derivs);
  state[1] += 0.5*dt*derivs[1]
  state[2] += 0.5*dt*derivs[2]
end

# Input/Output: state = [x,y,vx,vy], an array of two 2-d positions and velocities for a test particle
# Input: dt is the fixed time step
# Input: duration is the total
function integrate_leapfrog!(state::Vector{Float64}, dt::Float64, duration::Float64; max_num_log::Integer = 100000)
  @assert(length(state)==4)
  @assert(dt>0.0)
  @assert(duration>0.0)

  # Preallocate array to hold data log (including  initial state)
  nsteps = iceil(duration/dt);
  nskip = (nsteps<max_num_log) ? 1 : iceil(nsteps/(max_num_log-1))
  num_log = iceil(nsteps/nskip)+1
  log = Array(Float64,(num_log,length(state)));

  # Pre-allocate and pre-compute derivaties
  derivs = Array(Float64,4);
  update_derivs!(state,derivs);

  # Log initial state
  log_pos = 1
  log[log_pos,:] = deepcopy(state)

  n = 0
  t = 0.0
  while t<duration
    # ensure don't integrate for more than duration
    dt_tmp = (t+dt<=duration) ? dt : duration-t;

	# advance system by one time step
    advance_leapfrog!(state,derivs,dt_tmp, derivs_current=true)
    t = t + dt_tmp
    n = n + 1

    if (n%nskip==0) # Log data
	   log_pos += 1
   	   @assert( log_pos<=length(log) )
	   @assert( length(log[log_pos,:])==length(state) )
	   log[log_pos,:] = deepcopy(state)
	end
  end
  return log
end

function calc_error_leapfrog_old(dur::Float64, dt::Float64 = 2pi/200.0)
  state = [1.,0.,0.,1.];
  integrate_leapfrog!(state,dt,dur*2pi);
  dist = state[1]^2+state[2]^2
  phase = atan2(state[2],state[1])
  offset = sum((state[1:2].-[1.0,0.0]).^2)
  return (dist-1.0,phase,offset)
end

function calc_end_distance_leapfrog(dur::Integer, dt::Float64 = 2pi/200.0, state::Vector{Float64} = [1., 0., 0., 1.] )
  #state = [1.,0.,0.,1.];
  dist_init = sqrt(state[1]^2+state[2]^2)
  phase_init = atan2(state[2],state[1])
  integrate_leapfrog!(state,dt,dur*2pi);
  # Calculate three metrics of the accuracy of the integration
  dist = sqrt(state[1]^2+state[2]^2)
  phase = atan2(state[2],state[1])
  offset = sqrt(sum((state[1:2].-[1.0,0.0]).^2))
  return (dist-dist_init,phase-phase_init,offset)
end

using Base.Test
function test_leapfrog(dur::Integer, dt::Float64 = 2pi/200.0)
  err = calc_end_distance_leapfrog(dur,dt)
  @test_approx_eq_eps(err[1], 0., 1e-6)
  @test_approx_eq_eps(err[2], 0., 1e-1)
  @test_approx_eq_eps(err[3], 0., 1e-1)
end

ext: jl


text:
macro import_decoration_huge()
    :(
        using ComplexVisual:
            cv_border, cv_fill_rectangle_cb, cv_fill_circle_cb,
            cv_filled_canvas
    )
end

"""
create border(-callback) for a givven `CV_2DLayoutPosition`, adds
the border rectangle to the layout and recturns the `CV_2DLayoutPosition`
for this border decoration.

The parameter north, east, south, west define the border thickness.
"""
function cv_border(layout::CV_Abstract2DLayout, for_position::CV_2DLayoutPosition,
        north::Integer=2, east::Integer=north, south::Integer=north,
        west::Integer=east; gap_north::Integer=0, gap_east::Integer=gap_north,
        gap_south::Integer=gap_north, gap_west::Integer=gap_east,
        style=cv_black) # {{{

    rect = for_position.rectangle
    inner_rect = CV_Rectangle(
        rect.top + Int32(gap_south), rect.left - Int32(gap_west),
        rect.bottom - Int32(gap_north), rect.right + Int32(gap_east))
    outer_rect = CV_Rectangle(
        inner_rect.top + Int32(south), inner_rect.left - Int32(west),
        inner_rect.bottom - Int32(north), inner_rect.right + Int32(east))
    drawing_cb =  (cc, pos) -> begin
        set_fill_type(cc.ctx, Cairo.CAIRO_FILL_RULE_EVEN_ODD)
        rectangle(cc.ctx, outer_rect.left, outer_rect.bottom,
            cv_width(outer_rect), cv_height(outer_rect))
        rectangle(cc.ctx, inner_rect.left, inner_rect.bottom,
            cv_width(inner_rect), cv_height(inner_rect))
        fill(cc.ctx)
        return nothing
    end
    return cv_add_rectangle!(layout, outer_rect, drawing_cb, style)
end # }}}

"""
drawing callback (e.g. for `cv_add_rectangle!`) which fills the rectangle.

Typically used only for debugging purposes or for explaining something.
"""
function cv_fill_rectangle_cb(cc, pos)     # {{{
    rect = pos.rectangle
    rectangle(cc.ctx, rect.left, rect.bottom,
              cv_width(rect), cv_height(rect))
    fill(cc.ctx)
    return nothing
end   # }}}

"""
drawing callback (e.g. for `cv_add_rectangle!`) which fills the inscribed
circle.

Typically used only for debugging purposes or for explaining something.
"""
function cv_fill_circle_cb(cc, pos)  # {{{
    rect = pos.rectangle
    half_width, half_height = cv_half(cv_width(rect)), cv_half(cv_height(rect))
    new_sub_path(cc.ctx)
    arc(cc.ctx,
        rect.left + half_width,
        rect.bottom + half_height,
        min(half_width, half_height), 0.0, 2*pi)
    fill(cc.ctx)
    return nothing
end    # }}}

"""
CV_Std2DCanvas filled with the given style.

Typically used only for debugging.
"""
function cv_filled_canvas(width::Integer, height::Integer,
                          style::CV_ContextStyle) # {{{
    canvas = CV_Std2DCanvas(width, height)
    cv_create_context(canvas, style) do con
        rectangle(con.ctx, 0, 0, width, height)
        fill(con.ctx)
    end
    return canvas
end # }}}

# vim:syn=julia:cc=79:fdm=marker:sw=4:ts=4:


text:
using Test

using RenderJay

this_fn = @__FILE__
this_folder, _ = splitdir(this_fn)
scene_fn = joinpath(this_folder, "testplot_little_cornellboxes.xml")

println("Reading data...")
assets, geometries, palettes, geometry_bvhs, scene_bvh, skymap, camera = read_scene(scene_fn)
coords = create_coords(camera)

println("Testing the render_pixel() function...")
radiance = render_pixel(coords[1], assets, geometries, palettes, geometry_bvhs, scene_bvh, skymap, camera)

@test all(radiance .> 0.0)

max_stars_repo_name: martinvanleeuwen/RenderJay

max_issues_repo_name: martinvanleeuwen/RenderJay

max_forks_repo_name: martinvanleeuwen/RenderJay


text:
using PooksoftAlphaVantageDataStore

# ok, so lets build by user object -
my_current_dir = pwd()   # where am I?
path_to_config_file = my_current_dir*"/test/configuration/Configuration.json"

# build the api user model -
user_model_result = build_api_user_model(path_to_config_file)
user_model = checkresult(user_model_result)

# now that we have the userModel - lets populate the request dictionary -
required_api_keys = [
        "symbol"        ;   # ticker symbol -
        "function"      ;   # what function are we doing?
        "interval"      ;   # what interval: 1min, 5min, 15min, 30min, 60min, daily, weekly, monthly
        "time_period"   ;   # Number of data points used to calculate each moving average value. Positive integers are accepted (e.g., time_period=60, time_period=200)
        "series_type"   ;   # The desired price type in the time series. Four types are supported: close, open, high, low
        "datatype"      ;   # By default, datatype=json. Strings json and csv are accepted with the following specifications: json returns the daily time series in JSON format; csv returns the time series as a CSV (comma separated value) file.
        "apikey"        ;   # the API key
]
requestDictionary = Dict{String,Any}()
requestDictionary["apikey"] = user_model.alphavantage_api_key
requestDictionary["symbol"] = "ALLY"
requestDictionary["function"] = "RSI"
requestDictionary["interval"] = "daily"
requestDictionary["time_period"] = "14"
requestDictionary["series_type"] = "close"
requestDictionary["datatype"] = "json"
api_call_result = execute_relative_strength_index_api_call(requestDictionary)
df = checkresult(api_call_result)


text:
@testset "89.gray-code.jl" begin
    @test gray_code(2) == [0,1,3,2]
    @test gray_code(0) == [0]
end


text:
function folder_to_file(path::String)
    files= readdir(path)
    for i in files
        if isdir(string(path,"/",i))
            folder_to_file(string(path,"/",i))
        end
    end
    files= readdir(path)
    fs::Array{String}=[]
    for i in files
        if isfile(string(path,"/",i))
            push!(fs,i)
        end
    end
    for i in fs
        mv(string(path,"/",i), string(path,"_",i))
    end
end

function main()
    fl = readdir()
    for i in fl
        if isdir(i)
            folder_to_file(string(pwd(),"/",i))
        end
    end
end
main()

max_stars_repo_name: ditys/WebpMergeDecompose

max_issues_repo_name: ditys/WebpMergeDecompose

max_forks_repo_name: ditys/WebpMergeDecompose


text:
# ---
# title: 1047. Remove All Adjacent Duplicates In String
# id: problem1047
# author: Qling
# date: 2021-03-09
# difficulty: Easy
# categories: Stack
# link: <https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/description/>
# hidden: true
# ---
#
# Given a string `S` of lowercase letters, a _duplicate removal_ consists of
# choosing two adjacent and equal letters, and removing them.
#
# We repeatedly make duplicate removals on S until we no longer can.
#
# Return the final string after all such duplicate removals have been made.  It
# is guaranteed the answer is unique.
#
#
#
# **Example 1:**
#
#
#
#     Input: "abbaca"
#     Output: "ca"
#     Explanation:
#     For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move.  The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca".
#
#
#
#
# **Note:**
#
#   1. `1 <= S.length <= 20000`
#   2. `S` consists only of English lowercase letters.
#
#
## @lc code=start
using LeetCode

function remove_duplicates(S::String)::String
    stk = Char[]

    for ch in S
        if !isempty(stk) && stk[end] == ch
            pop!(stk)
        else
            push!(stk, ch)
        end
    end

    return join(stk)
end
## @lc code=end