elder_scrolling/README.md

186 lines
6.8 KiB
Markdown
Raw Normal View History

# Elder Scroll: Legends Coding Challenge
Don't you love homework?
2020-09-15 20:27:31 +00:00
## Synopsis
The Highspot Coding Challenge. The premise is to display a deck-builder
card catalog (such as Magic The Gathering, although in this case it's
Elder Scrolls) made available via a RESTful API. The requirements as
set out in the Code Challenge are:
### Requirements Checklist
FEAT Infinite scroll works. Sort-of. I've implemented a Cards/Card interface, but it's heavy and direct, with absolutely not a care in the world about how much memory your browser can give me. It only moves forward in time, and accumulates as it goes. The React is brutal and heavy, but for a prototype, eh... it's a prototype. I'm a firm believer in prototypes. Criticism: "Cards" is doing too much, and not enough. It would make more sense to have a moving window, showing no more than what it would take to show the user what is expected at that moment, with the ability to load high and low, keeping only what the user is _looking at_ in the DOM tree. Proposal: Cards needs a CardCollection proxy object, which the Cards view object (personal convention: TSX files are named for what they show, semantically; TS files may be suffixed with "Model" or "Collection", a'la Backbone, to seperate them from the views, if needed; "Model" objects are very rarely needed) taps it as the user moves up and down; the IntersectionObserver tool would be pretty good for this; and if the proxy actually _cached_ the fields it had already seen, it wouldn't be slow at all. The proxy object could also support the search feature by keeping two collections: one of the "whole" set, and one of the "last search" set; the proxy could swap between them as needed. Enhancement: Well, it could use a "zoom" feature with a nice overlay. It might even be lovely to have a second page with all the things I haven't shown, like attributes, subtype, rarity (not, not the pony), or keywords. Enhancement: It is possible to search based on set, attributes, and so forth, so a sidebar with those as filters would also be kinda cool.
2020-09-16 02:41:37 +00:00
- ✓ Show results in a card grid format with the image prominently displayed.
- ✓ Each card displays: Image, Name, Text, Set Name, and Type. Additional fields are optional.
- ✓ Display a loading indicator when communicating with the API.
- ✓ Use a responsive design that accommod_es, at minimum, desktop and mobile.
- ✓ Initially, fetch and display the first 20 results returned by the API.
- ✓ As the user scrolls down the page, load and append additional cards using "infinite scroll."
- ✓ Retrieve additional pages of results as-needed but do not load more than 20 cards with
2020-09-15 20:27:31 +00:00
each request.
- ✓ Allow the user to search for cards by Name.
FEAT Infinite scroll works. Sort-of. I've implemented a Cards/Card interface, but it's heavy and direct, with absolutely not a care in the world about how much memory your browser can give me. It only moves forward in time, and accumulates as it goes. The React is brutal and heavy, but for a prototype, eh... it's a prototype. I'm a firm believer in prototypes. Criticism: "Cards" is doing too much, and not enough. It would make more sense to have a moving window, showing no more than what it would take to show the user what is expected at that moment, with the ability to load high and low, keeping only what the user is _looking at_ in the DOM tree. Proposal: Cards needs a CardCollection proxy object, which the Cards view object (personal convention: TSX files are named for what they show, semantically; TS files may be suffixed with "Model" or "Collection", a'la Backbone, to seperate them from the views, if needed; "Model" objects are very rarely needed) taps it as the user moves up and down; the IntersectionObserver tool would be pretty good for this; and if the proxy actually _cached_ the fields it had already seen, it wouldn't be slow at all. The proxy object could also support the search feature by keeping two collections: one of the "whole" set, and one of the "last search" set; the proxy could swap between them as needed. Enhancement: Well, it could use a "zoom" feature with a nice overlay. It might even be lovely to have a second page with all the things I haven't shown, like attributes, subtype, rarity (not, not the pony), or keywords. Enhancement: It is possible to search based on set, attributes, and so forth, so a sidebar with those as filters would also be kinda cool.
2020-09-16 02:41:37 +00:00
- ✓ Use modern open-source web technologies to implement your solution (React, Backbone,
2020-09-15 20:27:31 +00:00
Angular, Vue, Underscore, etc.).
- ✓ Provide instructions for prerequisites, installation, and application setup and build in a
2020-09-15 20:27:31 +00:00
README file.
### Evaluation Criteria
- Are all stated requirements met?
- Does the application successfully build and run?
- Is the code well-organized and easy to understand?
- Does the code reflect contemporary web development techniques?
- Are functions and variables clearly named to express their purpose?
- Was the solution visually appealing?
- Were any scope decisions, TODO items, and known issues called out in
code comments or the README file?
### Available Resources
- Endpoint: https://api.elderscrollslegends.io/v1/cards
- Documentation: https://docs.elderscrollslegends.io/,
https://docs.elderscrollslegends.io/#api_v1cards_list
The API includes this note:
> NOTE: The Elder Scrolls Legends API is a free, third-party service
> built by an independent developer; it is not affiliated with Highspot,
> or with the intellectual property owners of Elder Scrolls
> Legends. Please help us use it responsibly.
2020-09-15 20:27:31 +00:00
## Initial impressions
This is a single-page application. The 'search' is more of a filter,
sending the `?name=<param>` to the `/cards` API endpoint. To meet the
requirements of the application, the `pageSize=20` argument must be
passed to the endpoint.
Startup seems to be relatively straightforward, and there won't be
anything fancy here: A flexbox will probably do just fine, as will a
progressive fill. I'm inclined to _not_ use MaterialUI here; it's
probably overkill. Just an application, with some nice CSS and a decent
cache.
For the search feature, we'll want to go with whatever the API offers,
but when clearing the search, let's go for a fast reload with no data
requirements. That's provide some speed when going back to the basics.
I won't be using the ServiceWorker, as I don't feel confident enough in
my familiarity with it to make it matter.
Also, because I'm a *nerd*, I can't start without first picking out a
theme: white on black, with a paper texture from my design library
desaturated, darkened, and rendered a seamless tile, using the Google
'Marcellus' font, which kinda sorta looks Tolkeinesque.
## Requirements
The following are all you need to have installed in order to get
started:
- NodeJS >= 10.0
- Yarn >= 1.18
- Git >= 2.0
Fetch the latest version from the git repository (this repository uses
the new "not master" terminology, so it may not be immediately visible
until you checkout the 'canon' branch), then install any prerequisites.
Assuming you have GNU Make installed:
``` shellsession
$ git clone https://git.elfsternberg.com/elf/elder_scrolling
$ cd elder_scrolling
$ git checkout canon
$ make serve
```
If you do NOT have GNU Make installed:
``` shellsession
$ git clone https://git.elfsternberg.com/elf/elder_scrolling
$ cd elder_scrolling
$ git checkout canon
$ yarn
$ yarn build
$ yarn run http-server build/
```
In both of the above, the server will be available on port 8080.
To run in dev mode:
``` shellsession
$ git clone https://git.elfsternberg.com/elf/elder_scrolling
$ cd elder_scrolling
$ git checkout canon
$ yarn
$ yarn server
```
The server will be available on port 3000.
If you have docker installed, you may run the app this way:
``` shellsession
$ git clone https://git.elfsternberg.com/elf/elder_scrolling
$ cd elder_scrolling
$ git checkout canon
$ docker build --tag elderscrolling:1.0 .
$ docker run --publish 8080:8080 --name elderscrolling --detach elderscrolling:1.0
```
The server will be available on port 8080. To stop the docker session,
remove it from the server, and clean up your disk space afterward:
``` shellsession
$ docker kill elderscrolling
$ docker rm elderscrolling
$ docker rmi elderscrolling:1.0
```
Note that this will not remove the node-alpine image on top of which
elderscrolling is build.
## Observations
This was a lot of fun. I don't know how "cheating" it was to use the
react-grid-layout library, or react-modal, but I'm always glad to let
the professionals do the work. Working "around" the way hooks really,
really want to avoid expensive paints, in order to get the search
feature working, was a lesson I know I've had before, but it always
frustrates me when I come across it.
2020-09-16 03:15:18 +00:00
There are lot of other things that could be done with the app, but this
is "good enough" for now without throwing something like Semantic or
Material at it. It's possible to search on fields other than `name`,
for example, and it would be nifty to be able to, say, see all the
Unique cards, or all the Creature cards, and so forth. That wasn't in
the requirements, and I've given you folks 8 hours already.
2020-09-16 03:15:18 +00:00
That may seem like a lot for such a minor project, but it's been awhile
since I last worked with React at this level, and it's also been awhile
since I got Emacs up and running with a proper JSX back-end. The LSP
server is pretty good, but there are still some rough edges. Using
`prettier` a lot, and setting the code into `strict` as much as
possible, was as helpful as always.
2020-09-16 03:15:18 +00:00
I think I'm going to take apart the scrolling library I used. It's a
native JS application with a React wrapper, rather than a full-on React
app "written in React," and I feel that there are lessons inside it I
could use.
2020-09-16 03:15:18 +00:00
## LICENSE
2020-09-16 03:15:18 +00:00
The Elder Scrolls, The Elder Scrolls: Legends, ZeniMax, Bethesda,
Bethesda Softworks and related logos are registered trademarks or
trademarks of ZeniMax Media Inc. This product is not produced, endorsed,
supported, or affiliated with ZeniMax Media Inc.
The original software contained in this repository is copyright [Kenneth
M. "Elf" Sternberg](https://elfsternberg.com) (c) 2020 as is licensed
with the Mozilla Public License vers. 2.0. A copy of the license file is
included in the root folder.
2020-09-16 03:15:18 +00:00