diff --git a/dev/Dockerfile b/dev/Dockerfile index 00482d6..59ef584 100644 --- a/dev/Dockerfile +++ b/dev/Dockerfile @@ -5,9 +5,22 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 RUN rm /etc/apache2/sites-enabled/000-default.conf RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql libapache2-mod-wsgi-py3 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y virtualenv +# make for testing +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y virtualenv make sudo RUN ln -s /data/dev/apache-local.conf /etc/apache2/sites-enabled/ #RUN a2enmod rewrite + +RUN sed -i "s#data_directory = '.*'#data_directory = '/data/run/postgres'#" /etc/postgresql/10/main/postgresql.conf +RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/10/main/pg_hba.conf +RUN echo "listen_addresses='*'" >> /etc/postgresql/10/main/postgresql.conf +RUN /etc/init.d/postgresql restart + +RUN sudo -u postgres psql -c "CREATE USER hoou WITH PASSWORD 'hoohoohoo123';" +RUN sudo -u postgres psql -c "CREATE DATABASE hoou;" +RUN sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE hoou to hoou;" + +# psql -h localhost -U hoou hoou # should work + CMD /data/dev/run-internal.sh diff --git a/dev/apache-local.conf b/dev/apache-local.conf index 1deedcb..4525b8d 100644 --- a/dev/apache-local.conf +++ b/dev/apache-local.conf @@ -1,61 +1,24 @@ - ServerAdmin admin@wr.informatik.uni-hamburg.de - ServerName oer.wr.informatik.uni-hamburg.de + ServerAdmin admin@hps.vi4io.org + #ServerName oer.hps.vi4io.org - Redirect permanent / https://oer.wr.informatik.uni-hamburg.de/ + WSGIScriptAlias / "/data/src/main/wsgi.py" + WSGIDaemonProcess hoou python-home=/data/run/virtualenv python-path=/data/src/ home=/data/src/ inactivity-timeout=10 request-timeout=10 + WSGIProcessGroup hoou + WSGIApplicationGroup %{GLOBAL} - - Options SymLinksIfOwnerMatch - AllowOverride None - Require all denied + DocumentRoot /data/src/ + Alias /static/ "/data/run/static/" + + + Require all granted + + + + Require all granted ErrorLog ${APACHE_LOG_DIR}/error.log LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined - - - - - ServerAdmin admin@wr.informatik.uni-hamburg.de - ServerName oer.wr.informatik.uni-hamburg.de - - #RewriteEngine on - #RewriteRule "^/$" "http://cluster.wr.informatik.uni-hamburg.de:8000/" [R,L] - #RewriteRule "^/(.+)$" "http://cluster.wr.informatik.uni-hamburg.de:8000/$1" [R,L] - - WSGIScriptAlias / "/home/hoou/git/HOOU/django-platform/main/wsgi.py" - WSGIDaemonProcess hoou python-home=/home/hoou/git/HOOU/virtualenv python-path=/home/hoou/git/HOOU/django-platform/ home=/home/hoou/git/HOOU/django-platform/ inactivity-timeout=10 request-timeout=10 - WSGIProcessGroup hoou - WSGIApplicationGroup %{GLOBAL} - - DocumentRoot /home/hoou/git/HOOU/django-platform/ - Alias /static/ "/home/hoou/git/HOOU/django-platform/apache/static/" - - - Require all granted - - - - Require all granted - - - ErrorLog ${APACHE_LOG_DIR}/error-oer.log - LogLevel warn - CustomLog ${APACHE_LOG_DIR}/oer-access.log combined - - SSLEngine on - SSLCertificateFile /etc/letsencrypt/live/oer.wr.informatik.uni-hamburg.de/fullchain.pem - SSLCertificateKeyFile /etc/letsencrypt/live/oer.wr.informatik.uni-hamburg.de/privkey.pem - - - Alias "/.well-known/acme-challenge/" "/var/www/certbot/.well-known/acme-challenge/" - - - Options SymLinksIfOwnerMatch - AllowOverride None - Require all granted - - - diff --git a/dev/requirements.txt b/dev/requirements.txt index 7a89108..cff4473 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -7,5 +7,5 @@ Sphinx pymongo celery markdown -psycopg2 +psycopg2-binary social-auth-app-django diff --git a/dev/run-internal.sh b/dev/run-internal.sh index 6b899f0..2145604 100755 --- a/dev/run-internal.sh +++ b/dev/run-internal.sh @@ -1,9 +1,16 @@ #!/bin/bash -e adduser --system --no-create-home --home /data --uid 1000 www-user sed -i "s/APACHE_RUN_USER=www-data/APACHE_RUN_USER=www-user/" /etc/apache2/envvars +sed -i "s#data_directory = '.*'#data_directory = '/data/run/postgres'#" /etc/postgresql/10/main/postgresql.conf + +/etc/init.d/postgresql restart + /etc/init.d/apache2 start tail -f /var/log/apache2/error.log & +export OER_SRC_DIR=/data/oer +export PLATFORM_PATH=/data/src + V="/data/run/virtualenv" if [[ ! -e $V ]] ; then mkdir -p $V @@ -11,6 +18,10 @@ if [[ ! -e $V ]] ; then cd $V source $V/bin/activate pip3 install -U -r /data/dev/requirements.txt + python3 ./manage.py migrate + python3 ./manage.py collectstatic fi +source $V/bin/activate + /bin/bash diff --git a/oer/README.md b/oer/README.md new file mode 100644 index 0000000..52eac25 --- /dev/null +++ b/oer/README.md @@ -0,0 +1,16 @@ +# Open Educational Resources + +While many standards for open educational resources (OER) are available. +Unfortunetly many ignore the special needs for automatic evaluation and grading +for programming courses and parallel programming in particular. As such, until +a more universal format is determined, this project sticks with a very +simple file and directory based format and mostly plaintext based metadata. +Tools to work with the web platform and execution runners are provided. + +## Structure + +Lectures/courses and exercises are decoupled, to allow for multiple courses to +use the same exercise. + + ./courses # a course allows to specify a sequence or directed graph of excercises + ./exercises # provides a pool of exercises which can be used to create courses diff --git a/oer/courses/c-advanced/meta b/oer/courses/c-advanced/meta new file mode 100644 index 0000000..433ef5d --- /dev/null +++ b/oer/courses/c-advanced/meta @@ -0,0 +1 @@ +{"title": "C Advanced", "description": "Some further material for the C-Programming-Language"} diff --git a/oer/courses/c-advanced/sections/01-introduction/00-weclome/content.md b/oer/courses/c-advanced/sections/01-introduction/00-weclome/content.md new file mode 100644 index 0000000..9fb8e20 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/00-weclome/content.md @@ -0,0 +1,10 @@ +Welcome to the C-Advanced course. This course is targeted for those, +who feel comfortable with pointers, memory management and all the basic +c syntax. + +We will guide you on, how to use c to implement your own data-structures, +writing your own libraries and give you some more advanced task to +test your abilities. + +Most of these task can take some time to get everything right. So don't be discouraged, whenn +need to take a break. Often those breaks help one see the mistakes or misunderstandings. diff --git a/oer/courses/c-advanced/sections/01-introduction/00-weclome/meta b/oer/courses/c-advanced/sections/01-introduction/00-weclome/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/00-weclome/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/c-advanced/sections/01-introduction/00-weclome/type b/oer/courses/c-advanced/sections/01-introduction/00-weclome/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/00-weclome/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/Makefile b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/content.md b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/content.md new file mode 100644 index 0000000..3a190bb --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/content.md @@ -0,0 +1,28 @@ +The first basic data-structure everybody should learn is the singly linked list. + +In a singly linked list you save your data in nodes, a combination of data and a pointer +to the next node. To add nodes you simply allocate them and rewire the pointers, +such that it appears in the right spot in the list. + +To remove an element you have to rewire the previous and next node, such that their +pointers point to each other, and then free the memory. + +The idea behind this data-structures is, that you can add and remove elements easily +from the end, front and middle of the list. And because you just allocate more memory, +the list can grow dynamically. + +The problem is to get to the elements. +Because they are allocated on the heap the elements are all over the place and can only +be found via the pointers. So, when you want to get to the middle, you have to traverse +the linked list. + +Another downside of singly linked list is, that you can't go backwards. +That is were the doubly linked list comes in, but more on that later. + +The last disadvantage is, when you want to process lot's of data in a short amount of time, +you are often limited by cache misses. And linked list in general are terrible for that kind +of work, because most elements aren't in the same cache line. + +Your task will be to implement the functions for add, insert_after, remove and get. +It is often helpful to draw the operations you want to do on paper or +look at some pictures. \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/meta b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/meta new file mode 100644 index 0000000..a615026 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/meta @@ -0,0 +1 @@ +{"title": "Singly Linked List"} diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/program.c b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/program.c new file mode 100644 index 0000000..edd4ef3 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/program.c @@ -0,0 +1,66 @@ +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + // TODO: implement this +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + // TODO: implement this +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + // TODO: implement this + + return 0; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // TODO: implement this +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + // TODO: implement this +} + +int main(int argc, char **argv) +{ + // NOTE: beginning of the list + // right now the list is empty + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + list_free(Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/regex b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/regex new file mode 100644 index 0000000..b77b142 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/regex @@ -0,0 +1 @@ +^a b c d $ diff --git a/oer/courses/c-advanced/sections/01-introduction/01-linked-list/type b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/01-linked-list/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/Makefile b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/content.md b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/content.md new file mode 100644 index 0000000..26c99bc --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/content.md @@ -0,0 +1,11 @@ +The next step up from a sinlgy linked list is the double linked list. +It is basically the same. It just stores another pointer for the previous node. +This makes some operations way easier and some a little harder. +But most of the time it is a trade of worth taking. + +A common thing people do is to make double linked list(in short dlist) circular. +To mark the head and the tail they use a special node called the sentinel. +This makes some operations easier, but for now we will concentrate on the basic dlist. + +Your task is to change the singly linked list to a double linked list. + diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/meta b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/meta new file mode 100644 index 0000000..44cf344 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/meta @@ -0,0 +1 @@ +{"title": "Double Linked List"} diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/program.c b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/program.c new file mode 100644 index 0000000..fd8c547 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/program.c @@ -0,0 +1,111 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; + struct node *Prev; +}node; + +// TODO: change all the function to use a dlinked list +node *alloc_node(char c, node *Next, node *Prev) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +// TIP: In the next 2 function you probably need to check for null-pointers +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + node *NewNode = alloc_node(c, *Head, 0); + *Head = NewNode; +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + node *NewNode = alloc_node(c, Node->Next, 0); + Node->Next = NewNode; +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + node *Result; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->Character == c) + { + Result = Iter; + break; + } + } + return Result; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // NOTE: this should get simpler + // Find prev node + node *Prev = 0; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter == Node) + break; + Prev = Iter; + } + if(Prev) + Prev->Next = Node->Next; + free(Node); +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} + +int main(int argc, char **argv) +{ + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(&Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + // NOTE: prints out the whole list + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + // NOTE: prints out the previous Node of B, B and the next one + node *B = list_get(&Head, 'b'); + if(B) + { + printf("%s %c %s\n",B->Prev? B->Prev: "Null", B->Character, B->Next? B->Next: "Null"); + } + + list_free(&Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/regex b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/regex new file mode 100644 index 0000000..f39781e --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/regex @@ -0,0 +1 @@ +^a b c d\s*a b c\s*$ diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/solution.c b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/solution.c new file mode 100644 index 0000000..718031c --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/solution.c @@ -0,0 +1,113 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; + struct node *Prev; +}node; + +// TODO: chane all the function to use a dlinked list +node *alloc_node(char c, node *Next, node *Prev) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + NewNode->Prev = Prev; + + return NewNode; +} + +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + node *NewNode = alloc_node(c, *Head, 0); + if(*Head) + (*Head)->Prev = NewNode; + *Head = NewNode; +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + node *NewNode = alloc_node(c, Node->Next, Node); + node *Next = Node->Next; + if(Next) + { + Next->Prev = NewNode; + } + Node->Next = NewNode; +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + node *Result; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->Character == c) + { + Result = Iter; + break; + } + } + return Result; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // NOTE: this should get simpler + // Find prev node + node *Prev = Node->Prev; + if(Prev) + Prev->Next = Node->Next; + node *Next = Node->Next; + Next->Prev = Prev; + + free(Node); +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} + +int main(int argc, char **argv) +{ + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(&Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + // NOTE: Prints out the whole list + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + node *B = list_get(&Head, 'b'); + if(B) + { + printf("%s %c %s\n",B->Prev? B->Prev: "Null", B->Character, B->Next? B->Next: "Null"); + } + list_free(&Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/test.c b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/test.c new file mode 100644 index 0000000..bfd5289 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/test.c @@ -0,0 +1,105 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, *Head); + *Head = NewNode; +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, Node->Next); + Node->Next = NewNode; +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + // TODO: implement this + node *Result; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->Character == c) + { + Result = Iter; + break; + } + } + return Result; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // TODO: implement this + // Find prev node + node *Prev = 0; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter == Node) + break; + Prev = Iter; + } + if(Prev) + Prev->Next = Node->Next; + free(Node); +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} + +int main(int argc, char **argv) +{ + // NOTE: beginning of the list + // right now the list is empty + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(&Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + list_free(&Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/type b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/02-dlink_list/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/Makefile b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/content.md b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/content.md new file mode 100644 index 0000000..2fda54c --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/content.md @@ -0,0 +1,21 @@ +The next data-structure is the hash table. +The hash table solves the problem of off having some key associated with +your data and wanting to get the entry in a table. + +In an normal array you would have to search the whole list. The same is +true for linked list. A hash table solves this problem by using the key as the index into an array. + +The key is normally referred to as the hash and is computed by putting your data trough a hash-function. + +The first problem you can easily imagine is, that two different entries get the same hash. This +is called a collision. There are different strategies of solving those collisions. +Some are inline solutions and use the next indices to store the entry others require other data-structures. + +Our hash-table will use a dlinked-list for these collision. If we detect a collision the new entry is +saved as the head of the linked list. + +A downside of a hash table is that it is hard to balance wasted space and avoiding collision. +You have to have a good hash function and good testing to determine with what kind of space you can +get away with. + +You task is to implement the hash table. \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/linked_list.h b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/linked_list.h new file mode 100644 index 0000000..89cb5db --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/linked_list.h @@ -0,0 +1,53 @@ +node *alloc_node(int Value, int x, int y, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->x = x; + NewNode->y = y; + NewNode->Next = Next; + + return NewNode; +} + +void list_add(node **Head, int Value, int x, int y) +{ + node *NewNode = alloc_node(Value, x, y, *Head); + *Head = NewNode; +} + +node *list_get(node **Head, int x, int y) +{ + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->x == x && Iter->y == y) + { + return Iter; + } + } + return 0; +} + +void list_remove(node **Head, node *Node) +{ + node *Prev = 0; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter == Node) + break; + Prev = Iter; + } + if(Prev) + Prev->Next = Node->Next; + free(Node); +} + +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/meta b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/meta new file mode 100644 index 0000000..8b8e851 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/meta @@ -0,0 +1 @@ +{"title": "Hash Table"} diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/program.c b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/program.c new file mode 100644 index 0000000..26c9461 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/program.c @@ -0,0 +1,110 @@ +#include +#include + +#define HASH_TABLE_SIZE 32 + +// NOTE: the data is some value, which is on a certain 2D point (x,y) +typedef struct node +{ + // the data + int x,y; + float Value; + + // next entry in the hash-table, if there were a collision + struct node *Next; +}node; + +#include "linked_list.h" + +/* + * Linked-list interface + * + * void list_add(node **Head, int Value, int x, int y); + * + * node *list_get(node **Head, int x, int y); + * + * void list_remove(node **Head, node *Node); + * + */ + +// NOTE: this computes the hash slot of the entry +int hash(int x, int y) +{ + int Result = (x + y)%HASH_TABLE_SIZE; + + if(Result < 0) + Result *= -1; + return Result; +} + +// NOTE: adds a new entry to the hash table. +// new entries go at the head of the linked-list +void hash_add(node **HashTable, float Value, int x, int y) +{ + // Don't forget to update the hash-tables pointer to the head. +} + +// NOTE: gets the note at the position (x,y) +node *hash_get(node **HashTable, int x, int y) +{ + return 0; +} + +// NOTE: removes the node at position (x,y), +// if there is one +void hash_remove(node **HashTable, int x, int y) +{ + +} + +int main(int argc, char *argv) +{ + node *HashTable[HASH_TABLE_SIZE] = {}; + + + // NOTE: some test values + hash_add(HashTable, 1.0, 1, 0); + hash_add(HashTable, 3.0, 0, 1); + hash_add(HashTable, 5.0, 3, -2); + hash_add(HashTable, 7.0, 10, 3); + + // NOTE: test adding with collisions + node *Node = hash_get(HashTable, 1, 0); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 1 at position (1,0)\n"); + + Node = hash_get(HashTable, 0, 1); + int added01 = 0; + if(Node) + { + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + added01 = 1; + } + else + printf("Failed to add or find value 3 at position (0,1)\n"); + + Node = hash_get(HashTable, 3, -2); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 5 at position (-2,-2)\n"); + + Node = hash_get(HashTable, 10, 3); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 7 at position (10,3)\n"); + + // NOTE: test removing element + if(added01) + { + hash_remove(HashTable, 0, 1); + Node = hash_get(HashTable, 0, 1); + if(!Node) + printf("Succesfully removed entrie at position (0,1) from the HashTable\n"); + else + printf("Failed to remove entrie at position (0,1)\n"); + } +} diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/regex b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/regex new file mode 100644 index 0000000..740730b --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/regex @@ -0,0 +1 @@ +^Succesfully added value 1.000000 at position (1,0) to the HashTable\nSuccesfully added value 3.000000 at position (0,1) to the HashTable\nSuccesfully added value 5.000000 at position (3,-2) to the HashTable\nSuccesfully added value 7.000000 at position (10,3) to the HashTable\nSuccesfully removed entrie at position (0,1) from the HashTable$ \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/solution.c b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/solution.c new file mode 100644 index 0000000..ab0d6bf --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/solution.c @@ -0,0 +1,116 @@ +#include +#include + +#define HASH_TABLE_SIZE 32 + +// NOTE: the data is some value, which is on a certain 2D point (x,y) +typedef struct node +{ + // the data + int x,y; + float Value; + + // next entrie in the hashtable, if there were a collision + struct node *Next; +}node; + +#include "linked_list.h" + +/* + * Linked-list interface + * + * void list_add(node **Head, int Value, int x, int y); + * + * node *list_get(node **Head, int x, int y); + * + * void list_remove(node **Head, node *Node); + * + */ + +int hash(int x, int y) +{ + int Result = (x + y)%HASH_TABLE_SIZE; + + if(Result < 0) + Result *= -1; + return Result; +} + +void hash_add(node **HashTable, float Value, int x, int y) +{ + int Hash = hash(x,y); + node *Head = HashTable[Hash]; + list_add(&Head, Value, x, y); + + // Don't forget to update the Hashtables pointer to the head. + HashTable[Hash] = Head; +} +node *hash_get(node **HashTable, int x, int y) +{ + int Hash = hash(x,y); + node *Head = HashTable[Hash]; + node *Result = list_get(&Head, x, y); + + return Result; +} + +void hash_remove(node **HashTable, int x, int y) +{ + int Hash = hash(x,y); + node *Head = HashTable[Hash]; + node *Node = list_get(&Head, x, y); + if(Node) + list_remove(&Head, Node); +} + +int main(int argc, char *argv) +{ + node *HashTable[HASH_TABLE_SIZE] = {}; + + //payload D1 = {0, 0, 1.0, 0}; + + hash_add(HashTable, 1.0, 1, 0); + hash_add(HashTable, 3.0, 0, 1); + hash_add(HashTable, 5.0, 3, -2); + hash_add(HashTable, 7.0, 10, 3); + + // Note: Test adding with collisions + node *Node = hash_get(HashTable, 1, 0); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 1 at position (1,0)\n"); + + Node = hash_get(HashTable, 0, 1); + int added01 = 0; + if(Node) + { + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + added01 = 1; + } + else + printf("Failed to add or find value 3 at position (0,1)\n"); + + Node = hash_get(HashTable, 3, -2); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 5 at position (-2,-2)\n"); + + Node = hash_get(HashTable, 10, 3); + if(Node) + printf("Succesfully added value %f at position (%d,%d) to the HashTable\n", Node->Value, Node->x, Node->y); + else + printf("Failed to add or find value 7 at position (10,3)\n"); + + // NOTE: Test removing element + if(added01) + { + hash_remove(HashTable, 0, 1); + Node = hash_get(HashTable, 0, 1); + if(!Node) + printf("Succesfully removed entrie at position (0,1) from the HashTable\n"); + else + printf("Failed to remove entrie at position (0,1)\n"); + } +} diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/test.c b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/test.c new file mode 100644 index 0000000..bfd5289 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/test.c @@ -0,0 +1,105 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, *Head); + *Head = NewNode; +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, Node->Next); + Node->Next = NewNode; +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + // TODO: implement this + node *Result; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->Character == c) + { + Result = Iter; + break; + } + } + return Result; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // TODO: implement this + // Find prev node + node *Prev = 0; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter == Node) + break; + Prev = Iter; + } + if(Prev) + Prev->Next = Node->Next; + free(Node); +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} + +int main(int argc, char **argv) +{ + // NOTE: beginning of the list + // right now the list is empty + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(&Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + list_free(&Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/03-hashtable/type b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/03-hashtable/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/Makefile b/oer/courses/c-advanced/sections/01-introduction/04-queue/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/content.md b/oer/courses/c-advanced/sections/01-introduction/04-queue/content.md new file mode 100644 index 0000000..99a17c2 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/content.md @@ -0,0 +1,18 @@ +As you noticed, we can use our basic data-structures, to form more complex ones, which fit more specific needs. +This time we will take a look at the queue. This data-structures allows you to perform operations on your data +with the **FIFO**(**F**irst **i**n **F**irst **o**ut) principle. This is critical, if you want to +process the oldest data first, just like in a queue in the real world. + +The queue data-structure is normally based on a linked list, such that it is also dynamically growing in size. +But this does not have to be true, but usually, if you are using libraries, it is. + +For the queue we want to perform three basic operations. + -first we want to put something at the end of the queue. We call that ``enqueue``. + -second we want to take something of the beginning of the queue. We call that ``dequeue``. + -third we want just look at the end of the queue without taking it of. We call that ``peak``. + +There are also other kinds of queues, which will not necessarily operate like a FIFO-queue. +For example the priority-queue, which will sort the member with the highest priority +to the beginning of the queue and uses a heap as it's underlying structure. + +Your task is to implement the queue on the basis of a singly linked list. diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/meta b/oer/courses/c-advanced/sections/01-introduction/04-queue/meta new file mode 100644 index 0000000..7b25b87 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/meta @@ -0,0 +1 @@ +{"title": "Queue"} diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/program.c b/oer/courses/c-advanced/sections/01-introduction/04-queue/program.c new file mode 100644 index 0000000..6f4a843 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/program.c @@ -0,0 +1,70 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +typedef struct +{ + node *Head; + node *Tail; +}queue; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +// You could reuse the implementation of the singly linked list, +// but in this case we can optimize our operations, +// because we have pointers to the beginning end of the linked list. + +// NOTE: this put elements on the end of the list +// Don't forget to initialize the Head pointer +void enqueue(queue *Queue, char c) +{ + // TODO: implement this +} + +// NOTE: This returns the char, because we don't want to manage +// the memory in "user code" +// Don't forget to free the node, otherwise this queue has a leak. +char dequeue(queue *Queue) +{ + // TODO: implement this + return 0; +} + +// NOTE: in this example we only use this to check if the list is empty. +// To do that we could also track the element count, but the peak operation +// has also some other use cases. +node *peak(queue *Queue) +{ + // TODO: implement this + return 0; +} + +// you can implement the queue-operations without ever searching through the list. +int main(int argc, char **argv) +{ + queue Queue = {}; + char *String = "HelloWorld!"; + + // The String should come out as it went in. + while(*String) + { + enqueue(&Queue, *String++); + } + while(peak(&Queue)) + { + printf("%c", dequeue(&Queue)); + } + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/regex b/oer/courses/c-advanced/sections/01-introduction/04-queue/regex new file mode 100644 index 0000000..deb08d0 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/regex @@ -0,0 +1 @@ +^HelloWorld!$ diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/solution.c b/oer/courses/c-advanced/sections/01-introduction/04-queue/solution.c new file mode 100644 index 0000000..80d9192 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/solution.c @@ -0,0 +1,69 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +typedef struct +{ + node *Head; + node *Tail; +}queue; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +void enqueue(queue *Queue, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, 0); + if(Queue->Tail) + Queue->Tail->Next = NewNode; + Queue->Tail = NewNode; + if(!Queue->Head) + { + Queue->Head = NewNode; + } +} + + +char dequeue(queue *Queue) +{ + // TODO: implement this + node *First = Queue->Head; + char Result = First->Character; + Queue->Head = First->Next; + free(First); + return Result; +} + +node *peak(queue *Queue) +{ + // TODO: implement this + return Queue->Head; +} + +int main(int argc, char **argv) +{ + queue Queue = {}; + char *String = "HelloWorld!"; + + while(*String) + { + enqueue(&Queue, *String++); + } + while(peak(&Queue)) + { + printf("%c", dequeue(&Queue)); + } + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/test.c b/oer/courses/c-advanced/sections/01-introduction/04-queue/test.c new file mode 100644 index 0000000..bfd5289 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/test.c @@ -0,0 +1,105 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +// NOTE: adds an element to the beginning +void list_add(node **Head, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, *Head); + *Head = NewNode; +} + +// NOTE: inserts after a specific node +void list_insert_after(node *Node, char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, Node->Next); + Node->Next = NewNode; +} + +// NOTE: get's a node with the specified character +node *list_get(node **Head, char c) +{ + // TODO: implement this + node *Result; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter->Character == c) + { + Result = Iter; + break; + } + } + return Result; +} + +// NOTE: removes a specific node from the list +void list_remove(node **Head, node *Node) +{ + // TODO: implement this + // Find prev node + node *Prev = 0; + for(node *Iter = *Head; Iter; Iter = Iter->Next) + { + if(Iter == Node) + break; + Prev = Iter; + } + if(Prev) + Prev->Next = Node->Next; + free(Node); +} + +// NOTE: frees the whole list +void list_free(node **Head) +{ + for(node *Iter = *Head; Iter; ) + { + node *ToFree = Iter; + Iter = Iter->Next; + + free(ToFree); + } +} + +int main(int argc, char **argv) +{ + // NOTE: beginning of the list + // right now the list is empty + node *Head = 0; + + list_add(&Head, 'c'); + list_add(&Head, 'y'); + list_add(&Head, 'b'); + + node *ToBeRemoved = list_get(&Head, 'y'); + list_remove(&Head, ToBeRemoved); + + list_add(&Head, 'a'); + node *InsertAfter = list_get(&Head, 'c'); + list_insert_after(InsertAfter, 'd'); + + for(node *Iter = Head; Iter; Iter = Iter->Next) + { + printf("%c ", Iter->Character); + } + printf("\n"); + + list_free(&Head); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/04-queue/type b/oer/courses/c-advanced/sections/01-introduction/04-queue/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/04-queue/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/Makefile b/oer/courses/c-advanced/sections/01-introduction/05-stack/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/content.md b/oer/courses/c-advanced/sections/01-introduction/05-stack/content.md new file mode 100644 index 0000000..347c6d6 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/content.md @@ -0,0 +1,17 @@ +A data-structure often associated with the queue is the stack. +That's because they are basically the opposite of one another. +While the queue works on the FIFO-principle the stack works +on the **LIFO**-principle (**L**ast **i**n **f**irst **o**ut). + +Similar two the queue we have three basic operations, but they are called +different to distinguish between the stack and the queue. + - We put something at the top of the stack. That is called push. + - We take something from the top of the stack. That is called pop. + - As with the queue we sometimes one to just take a look at the top of the stack. + So a peak operation is nice, but not necessary + +Stacks are useful data-structures for parsing or when you want follow some data to the end +and then back trace to a previous state, like in depth-fist-search. +These are just some use cases for stacks, but they have many more. + +Your task is to implement the push, pop and peak functions for the stack. \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/meta b/oer/courses/c-advanced/sections/01-introduction/05-stack/meta new file mode 100644 index 0000000..3bd5879 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/meta @@ -0,0 +1 @@ +{"title": "Stack"} diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/program.c b/oer/courses/c-advanced/sections/01-introduction/05-stack/program.c new file mode 100644 index 0000000..88a28ef --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/program.c @@ -0,0 +1,57 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +typedef struct +{ + node *Top; +}stack; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +void push(stack *Stack,char c) +{ + // TODO: implement this +} + +// NOTE: as last time free the node here +char pop(stack *Stack) +{ + // TODO: implement this + return 0; +} + +node *peak(stack *Stack) +{ + // TODO: implement this + return 0; +} + +int main(int argc, char **argv) +{ + stack Stack = {}; + char *String = "!dlroW ollaH"; + + // When everything works, the program should print Hello World!. + while(*String) + { + push(&Stack, *String++); + } + while(peak(&Stack)) + { + printf("%c", pop(&Stack)); + } + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/regex b/oer/courses/c-advanced/sections/01-introduction/05-stack/regex new file mode 100644 index 0000000..4391264 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/regex @@ -0,0 +1 @@ +^Hello World!$ diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/solution.c b/oer/courses/c-advanced/sections/01-introduction/05-stack/solution.c new file mode 100644 index 0000000..b1c9311 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/solution.c @@ -0,0 +1,62 @@ +#include +#include + +typedef struct node +{ + char Character; + struct node *Next; +}node; + +typedef struct +{ + node *Top; +}stack; + +node *alloc_node(char c, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Character = c; + NewNode->Next = Next; + + return NewNode; +} + +void push(stack *Stack,char c) +{ + // TODO: implement this + node *NewNode = alloc_node(c, Stack->Top); + Stack->Top = NewNode; +} + +char pop(stack *Stack) +{ + // TODO: implement this + char Result = Stack->Top->Character; + node *Top = Stack->Top->Next; + free(Stack->Top); + Stack->Top = Top; + return Result; +} + +node *peak(stack *Stack) +{ + // TODO: implement this + return Stack->Top; +} + +int main(int argc, char **argv) +{ + stack Stack = {}; + char *String = "!dlroW olleH"; + + // When everything works, the program should print Hello World!. + while(*String) + { + push(&Stack, *String++); + } + while(peak(&Stack)) + { + printf("%c", pop(&Stack)); + } + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/05-stack/type b/oer/courses/c-advanced/sections/01-introduction/05-stack/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/05-stack/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/Makefile b/oer/courses/c-advanced/sections/01-introduction/06-tree/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/content.md b/oer/courses/c-advanced/sections/01-introduction/06-tree/content.md new file mode 100644 index 0000000..4fee8cd --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/content.md @@ -0,0 +1,26 @@ +Now that we covered the basic linear data-structures, let's move on to once, which branch out. +This task is about trees. A tree consists of connected nodes and each node has a certain amount of children nodes. +The nodes, which don't have any children are called leaves and the start node is called a root. +A tree also doesn't have any circles, meaning that no path from one node should lead back to it's self. +Trees are often associated with sorting, hierarchical data or decisions. + +This description is for trees in general. The one we will discuss is called a binary-search-tree. +The only difference to the normal tree is, that it only has two children and all the left children have a lower +search value than the node and all the right nodes have a higher one. +These kind of trees are very useful for efficient searching. + +For this tree we want to be able to perform four operations. + - We want to be able to automatically insert an element into the right place. + - We want to delete an element without destroying the definition of the binary-search-tree + - We want to find an element in the tree + - And we want to print out all the elements in a sorted way + +Recursion is a good strategy to write functions for trees. + +All but the delete functions are straight forward. The delete function needs some special casing. +If there are both children present, you have to find the lowest value on the right and replace the +current one with it and then recursivly delete that one. +If there are less than two children, the deletion is trivial. + +Your task is to implement all these functions. + diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/meta b/oer/courses/c-advanced/sections/01-introduction/06-tree/meta new file mode 100644 index 0000000..9a5301d --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/meta @@ -0,0 +1 @@ +{"title": "Tree"} diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/program.c b/oer/courses/c-advanced/sections/01-introduction/06-tree/program.c new file mode 100644 index 0000000..41fc0a7 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/program.c @@ -0,0 +1,89 @@ +#include +#include + +typedef struct node +{ + int Value; + struct node *Left; + struct node *Right; +}node; + +node *alloc_node(int Value, node *Left, node *Right) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->Left = Left; + NewNode->Right = Right; + + return NewNode; +} + +// inserts into the right place in the tree +void tree_insert(node *Root, int Value) +{ + // TODO: implement this +} + +// finds the node with the given value. +// if it doesn't find one return null +node *tree_find(node *Root, int Value) +{ + // TODO: implement this + return 0; +} + +// deletes the node with the value while remaining sorted +// NOTE: feel free to change the function signiture +void tree_delete(node *Root, int Value) +{ + // TODO: implement this + + // NOTE: when finding the node to delete, + // keep track of the parent node to rewire + // the pointer when deleting + + // NOTE: don't forget to free the memory +} + +// prints every member in a sorted way +int tree_print_sorted(node *Root) +{ + // TODO: implement this +} + +int main(int argc, char **argv) +{ + node Root = {}; + int Numbers[10] = {9, 128, 3, 1, 42, 9001, 7, 500, 6, 10}; + + // NOTE: filling the tree with numbers + for(int i = 0 ; i < 10; i++) + { + tree_insert(&Root, Numbers[i]); + } + + node *Nine = tree_find(&Root, 9); + int FoundNine = 0; + if(Nine) + { + FoundNine = 1; + node *Left = Nine->Left; + node *Right = Nine->Right; + printf("Found %d with direct child %d and %d\n", Nine->Value, (Left)? Left->Value: 0, (Right)? Right->Value : 0); + } + tree_delete(&Root, 9); + Nine = tree_find(&Root, 9); + if(Nine) + { + printf("Failed to delete %d\n", Nine->Value); + } + else + { + if(FoundNine) + printf("Succesfully deleted 9\n"); + } + + tree_print_sorted(&Root); + printf("\n"); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/regex b/oer/courses/c-advanced/sections/01-introduction/06-tree/regex new file mode 100644 index 0000000..a02c3c7 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/regex @@ -0,0 +1 @@ +^Found 9 with direct child 3 and 128\nSuccesfully deleted 9\n1 3 6 7 9 10 42 128 500 9001 $ diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/solution.c b/oer/courses/c-advanced/sections/01-introduction/06-tree/solution.c new file mode 100644 index 0000000..11df4a0 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/solution.c @@ -0,0 +1,176 @@ +#include +#include + +typedef struct node +{ + int Value; + struct node *Left; + struct node *Right; +}node; + +node *alloc_node(int Value, node *Left, node *Right) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->Left = Left; + NewNode->Right = Right; + + return NewNode; +} + +// inserts into the right place in the tree +void tree_insert(node **Root, int Value) +{ + // TODO: implement this + if(*Root) + { + node *Node = *Root; + if(Value <= Node->Value) + { + tree_insert(&Node->Left, Value); + } + else + { + tree_insert(&Node->Right, Value); + } + + } + else + { + *Root = alloc_node(Value, 0, 0); + } +} + +// finds the node with the given value. +// if it doesn't find one return null +node *tree_find(node *Root, int Value) +{ + // TODO: implement this + node *Node = Root; + if(Node) + { + if(Value < Node->Value) + { + tree_find(Node->Left, Value); + } + else if(Value > Node->Value) + { + tree_find(Node->Right, Value); + } + else + { + return Node; + } + } + return 0; +} + +// deletes the node with the value while remaining sorted +void tree_delete(node **Root, node *Parent, int Value) +{ + node *Node = *Root; + if(Node) + { + if(Value < Node->Value) + { + tree_delete(&Node->Left, Node, Value); + } + else if(Value > Node->Value) + { + tree_delete(&Node->Right, Node, Value); + } + else // Found node + { + node *NodeToDelete = Node; + if(NodeToDelete->Left && NodeToDelete->Right) + { + node *RightSubTree = NodeToDelete->Right; + if(RightSubTree) + { + node *LowestNode = RightSubTree->Left; + node *Prev; + while(LowestNode->Left) + { + Prev = LowestNode; + LowestNode = LowestNode->Left; + } + NodeToDelete->Value = LowestNode->Value; + Prev->Left = 0; + tree_delete(&LowestNode, Prev, LowestNode->Value); + } + } + else if(NodeToDelete->Left) + { + if(Parent) + Parent->Left = NodeToDelete->Left; + free(NodeToDelete); + } + else if(NodeToDelete->Right) + { + if(Parent) + Parent->Left = NodeToDelete->Right; + free(NodeToDelete); + } + else + { + if(Parent) + Parent->Left = 0; + free(NodeToDelete); + } + } + } + + // TODO: implement this +} + +// prints every member in a sorted way +void tree_print_sorted(node *Root) +{ + // TODO: implement this + node *Node = Root; + if(Node) + { + node *Left = Node->Left; + tree_print_sorted(Left); + printf("%d ", Node->Value); + node *Right = Node->Right; + tree_print_sorted(Right); + } +} + +int main(int argc, char **argv) +{ + node *Root; + int Numbers[10] = {9, 128, 3, 1, 42, 9001, 7, 500, 6, 10}; + + // NOTE: filling the tree with numbers + for(int i = 0 ; i < 10; i++) + { + tree_insert(&Root, Numbers[i]); + } + + node *Nine = tree_find(Root, 9); + int FoundNine = 0; + if(Nine) + { + FoundNine = 1; + node *Left = Nine->Left; + node *Right = Nine->Right; + printf("Found %d with direct child %d and %d\n", Nine->Value, (Left)? Left->Value: 0, (Right)? Right->Value : 0); + } + tree_delete(&Root, 0, 9); + Nine = tree_find(Root, 9); + if(Nine) + { + printf("Failed to delete %d\n", Nine->Value); + } + else + { + if(FoundNine) + printf("Succesfully deleted 9\n"); + } + + tree_print_sorted(Root); + printf("\n"); + +} diff --git a/oer/courses/c-advanced/sections/01-introduction/06-tree/type b/oer/courses/c-advanced/sections/01-introduction/06-tree/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/06-tree/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/Makefile b/oer/courses/c-advanced/sections/01-introduction/07-graphs/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/a.out b/oer/courses/c-advanced/sections/01-introduction/07-graphs/a.out new file mode 100755 index 0000000..28caeeb Binary files /dev/null and b/oer/courses/c-advanced/sections/01-introduction/07-graphs/a.out differ diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/content.md b/oer/courses/c-advanced/sections/01-introduction/07-graphs/content.md new file mode 100644 index 0000000..264535d --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/content.md @@ -0,0 +1,25 @@ +The last data-structure we are going to cover is the graph. +It is similar to a tree. In fact a tree is a special case +of a graph, because a graph is also allowed to have circles, +nodes that have a path to them self. + +Graphs are useful data-structure to encode relations. +For example a road-network or friendships. + +To encode the most basic graphs you need two things. +A list of nodes, sometimes called vertices, and a list of edges. +The nodes represent objects and the edges represent their relation. + +For example you could have a graph of a road-network, where every +intersection is a node and every street is an edge. + +With the edges and nodes you could encode more information, to use in your +algorithm. So the intersections could have an GPS-position and the street +some kind of cost, which indicates the amount of time you need to get to the +other side. + +In this task we provided you with a very simplistic graph, +which encodes the relationship between two people. +Your task is to find out, who likes one, which likes them back. + + diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/meta b/oer/courses/c-advanced/sections/01-introduction/07-graphs/meta new file mode 100644 index 0000000..b5fa1b3 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/meta @@ -0,0 +1 @@ +{"title": "Graphs"} diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/program.c b/oer/courses/c-advanced/sections/01-introduction/07-graphs/program.c new file mode 100644 index 0000000..9eeb04f --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/program.c @@ -0,0 +1,40 @@ +#include +#include + +int main(int argc, char **argv) +{ + // NOTE: These are the nodes + char *Names[5] = + { + "Mike", + "Bob", + "Anna", + "Emma", + "Nick" + }; + + // NOTE: These are the edges + // for now everyone can only like two other people + int Likes[5][2] = + { + {1,3}, // Mike likes Bob and Emma + {4,3}, + {0,4}, + {2,4}, + {1,2} + }; + + // NOTE: if you wanted to be able to have as much edges as possible + // you could use a 2D-Array with the size of the number + // of Nodes. These Arrays are called adjacency-matrices. + // But these are inherently inefficient, when you have a graph with + // few connections. + + // there are also other ways like storing the edges in the nodes + // in a list of pointers etc + + // TODO: print out everyone, who likes one, which likes them back. + // if you want to you can try to prevent duplicates like A likes B + // and B likes A, but this is not required. + printf("%s and %s both like each other.\n", "Nobody", "No one"); +} diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/regex b/oer/courses/c-advanced/sections/01-introduction/07-graphs/regex new file mode 100644 index 0000000..9cc7318 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/regex @@ -0,0 +1 @@ +^Bob and Nick both like eachother.\nAnna and Nick both like eachother.(\nNick and Bob both like eachother.\nNick and Anna both like eachother.){0,1}$ \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/solution.c b/oer/courses/c-advanced/sections/01-introduction/07-graphs/solution.c new file mode 100644 index 0000000..32259a0 --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/solution.c @@ -0,0 +1,42 @@ +#include +#include + +int main(int argc, char **argv) +{ + // NOTE: These are the nodes + char *Names[5] = + { + "Mike", + "Bob", + "Anna", + "Emma", + "Nick" + }; + + // NOTE: These are the edges + // for now everyone can only like two other people + int Likes[5][2] = + { + {1,3}, // Mike likes Bob and Emma + {4,3}, + {0,4}, + {2,4}, + {1,2} + }; + // TODO: print out everyone, who likes one, which likes them back + + for(int i = 0; i < 5; i++) + { + for(int j = 0; j < 2; j++) + { + int iLikes = Likes[i][j]; + for(int k = 0; k < 2; k++) + { + if(Likes[iLikes][k] == i) + { + printf("%s and %s both like each other.\n", Names[i], Names[iLikes]); + } + } + } + } +} diff --git a/oer/courses/c-advanced/sections/01-introduction/07-graphs/type b/oer/courses/c-advanced/sections/01-introduction/07-graphs/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/07-graphs/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-advanced/sections/01-introduction/section b/oer/courses/c-advanced/sections/01-introduction/section new file mode 100644 index 0000000..63820ed --- /dev/null +++ b/oer/courses/c-advanced/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Basic Datastructures", "description": "Implement your own Datastrucutes"} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/Makefile b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/Makefile new file mode 100644 index 0000000..5490f3f --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/Makefile @@ -0,0 +1,7 @@ + +all: + gcc -std=c99 -pthread program.c -o program + gcc -std=c99 -pthread solution.c -o solution +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/content.md b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/content.md new file mode 100644 index 0000000..4efe668 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/content.md @@ -0,0 +1,14 @@ +The first usecase we are going to take a look at, is about the queue. +There are trivial ones like a playlist, where you can add more music to. +Another common usecase is the breadth first search for a tree traversal. +But we are going to look at a more general concept. + +Imagine you have some code, which produces some data and another part, which +processes the data. This doesn't necessarily have to be in sync. +Specially when you talk about different threads or processes. +You then need a way to buffer the incomming data, otherwise you would +overwrite the oldes one, which, depending on the circumstances, can lead to errors. +A queue helps to get around this problem. + +For this exercise we prepared a thread, which just produces some random numbers and pushes them on a queue. +Your task is to add the oldest two together and print them out. \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/execute.sh b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/execute.sh new file mode 100755 index 0000000..49cee33 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/execute.sh @@ -0,0 +1,3 @@ +rand=$(( $RANDOM % 100)) +./program $rand + diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/meta b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/meta new file mode 100644 index 0000000..d2f69bf --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/meta @@ -0,0 +1 @@ +{"title": "Producer & Consumer"} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/program.c b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/program.c new file mode 100644 index 0000000..6e43001 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/program.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + + +typedef struct node +{ + int Value; + struct node *Next; +}node; + +typedef struct +{ + node *Head; + node *Tail; + pthread_mutex_t Mutex; +}queue; + +node *alloc_node(int Value, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->Next = Next; + + return NewNode; +} + +// NOTE: we are not going to talk about threads. +// the lock and unlock functions prevent the threads to execute the locked part at the same time, +// which could lead to errors +void enqueue(queue *Queue, int Value) +{ + node *NewNode = alloc_node(Value, 0); + pthread_mutex_lock(&Queue->Mutex); + if(Queue->Tail) + Queue->Tail->Next = NewNode; + Queue->Tail = NewNode; + if(!Queue->Head) + { + Queue->Head = NewNode; + } + pthread_mutex_unlock(&Queue->Mutex); +} + + +int dequeue(queue *Queue) +{ + pthread_mutex_lock(&Queue->Mutex); + node *First = Queue->Head; + int Result = First->Value; + Queue->Head = First->Next; + free(First); + pthread_mutex_unlock(&Queue->Mutex); + return Result; +} + +node *peak(queue *Queue) +{ + return Queue->Head; +} + +queue CommunicationQueue; + +void *Producer_Proc(void *ptr) +{ + int Seed = atoi((char *)ptr); + srand(Seed); + for (int i = 0; i < 100; i ++) + { + enqueue(&CommunicationQueue, (rand()%10)+1); + } + return 0; +} + +int main(int argc, char **argv) +{ + CommunicationQueue.Head = 0; + CommunicationQueue.Tail = 0; + pthread_mutex_init(&CommunicationQueue.Mutex,0); + + pthread_t Producer; + + pthread_create(&Producer, 0, Producer_Proc, (void *)argv[1]); + + // TODO: print 50 times the sum of the last two numbers from the queue + // don't forget to check if there is even anything on the queue + + pthread_join(Producer, 0); + + return 0; +} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/solution.c b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/solution.c new file mode 100644 index 0000000..8116aea --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/solution.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + + +typedef struct node +{ + int Value; + struct node *Next; +}node; + +typedef struct +{ + node *Head; + node *Tail; + pthread_mutex_t Mutex; +}queue; + +node *alloc_node(int Value, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->Next = Next; + + return NewNode; +} + +// NOTE: we are not going to talk about threads. +// the lock and unlock functions prevent the threads to execute the locked part at the same time, +// which could lead to errors +void enqueue(queue *Queue, int Value) +{ + node *NewNode = alloc_node(Value, 0); + pthread_mutex_lock(&Queue->Mutex); + if(Queue->Tail) + Queue->Tail->Next = NewNode; + Queue->Tail = NewNode; + if(!Queue->Head) + { + Queue->Head = NewNode; + } + pthread_mutex_unlock(&Queue->Mutex); +} + + +int dequeue(queue *Queue) +{ + pthread_mutex_lock(&Queue->Mutex); + node *First = Queue->Head; + int Result = First->Value; + Queue->Head = First->Next; + free(First); + pthread_mutex_unlock(&Queue->Mutex); + return Result; +} + +node *peak(queue *Queue) +{ + return Queue->Head; +} + +queue CommunicationQueue; + +void *Producer_Proc(void *ptr) +{ + int Seed = atoi((char *)ptr); + srand(Seed); + for (int i = 0; i < 100; i ++) + { + enqueue(&CommunicationQueue, (rand()%10)+1); + } + return 0; +} + +int main(int argc, char **argv) +{ + CommunicationQueue.Head = 0; + CommunicationQueue.Tail = 0; + pthread_mutex_init(&CommunicationQueue.Mutex,0); + + pthread_t Producer; + + if(argc < 2) + argv[1] = "1"; + pthread_create(&Producer, 0, Producer_Proc, (void *)argv[1]); + + for(int i = 0; i < 50; i++) + { + while(!peak(&CommunicationQueue)){} + int x = dequeue(&CommunicationQueue); + + while(!peak(&CommunicationQueue)){} + int y = dequeue(&CommunicationQueue); + + printf("%d\n", x+y); + } + + pthread_join(Producer, 0); + + return 0; +} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/test.sh b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/test.sh new file mode 100755 index 0000000..527dcf3 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/test.sh @@ -0,0 +1,12 @@ +rand=$(( $RANDOM % 100)) + +program_out=$(./program $rand) +solution_out=$(./solution $rand) + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false +fi diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/type b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/01_producer_consumer/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/Makefile b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/Makefile new file mode 100644 index 0000000..ba791c1 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/content.md b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/content.md new file mode 100644 index 0000000..d2d3349 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/content.md @@ -0,0 +1,10 @@ +For this task you are going to implement a very simple calculater using a stack. +To simplify this we are ignoring precedence and use post-fix operators (sometimes referred to as reverse polish notation). Post-fix operators are just like your normal infix ones. You just write them +at the end of the two operands. For example 3 + 4 becomes 3 4 +. This makes parsing way easier. +And because we are ignoring precedence, the term 3 4 5 + * is equal to 35. + +The concept of a stack based calculator is pretty simple. Numbers simply get pushed on the stack and +operators pop the number of operands of the stack, calculate the result and push it back on. +At the end you can just pop of the result. + +Because the parsing and the calculator would be a bit much for one task, we already implemented the parsing. Your task is to fill in the rest of the calculator. \ No newline at end of file diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/execute.sh b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/execute.sh new file mode 100755 index 0000000..64041fc --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/execute.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +arguments=$(./term_generator.sh) + +program_out=$(./program "$arguments") + +echo "term: $arguments" +echo "$program_out" + + + diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/meta b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/meta new file mode 100644 index 0000000..01e5fa4 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/meta @@ -0,0 +1 @@ +{"title": "Stack - Calculator"} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/program.c b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/program.c new file mode 100644 index 0000000..0f45346 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/program.c @@ -0,0 +1,115 @@ +#include +#include +#include "stack.h" + +// +// NOTE: helper functions for parsing +// +bool isWhitespace(char c) +{ + return(c == ' ' || c == '\t' || c == '\n' || c == '\r' ); +} + +char *eatAllWhitespaces(char *At) +{ + while(*At && isWhitespace(*At)) + At++; + return At; +} + +bool isDigit(char Digit) +{ + return (Digit >= '0' && Digit <= '9'); +} + +int isNumber(char *Number) +{ + int Result = 0; + while(*Number && *Number != ' ') + { + if(!isDigit(*Number)) + { + Result = -1; + return Result; + } + Number++; + Result++; + } + + return Result; +} +// +// ---------------------------------- +// + + +/* + * Stack-Interface + * + * void push(stack *Stack, float Value); + * + * float pop(stack *Stack); + * + * node *peak(stack *Stack); + * + */ + +int main(int argc, char **argv) +{ + stack Stack = {}; + + // + // Parsing + // + + // NOTE: the string to parse + char *Input = argv[1]; + char *At = Input; + while(*At) + { + At = eatAllWhitespaces(At); + switch(*At) + { + case '+': + { + // TODO: implement addition + }break; + case '-': + { + // TODO: implement substraction + // NOTE: substraction is orderdependent + }break; + case '*': + { + // TODO: implement multiplication + }break; + case '/': + { + // TODO: implement division + // NOTE: division is orderdependent + }break; + default: + { + int Length = isNumber(At); + if(Length != -1) + { + // TODO: implement the handling of new numbers + At += Length -1; + } + else + { + printf("ERROR: Only Numbers and Operators + - * and / are allowed"); + } + } + } + At++; + } + + // NOTE: print out the remaining stack + // if everything went right, this should only be the result + while(peak(&Stack)) + { + printf("%f ", pop(&Stack)); + } + printf("\n"); +} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/solution.c b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/solution.c new file mode 100644 index 0000000..2999176 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/solution.c @@ -0,0 +1,100 @@ +#include +#include +#include "stack.h" + +bool isWhitespace(char c) +{ + return(c == ' ' || c == '\t' || c == '\n' || c == '\r' ); +} + +char *eatAllWhitespaces(char *At) +{ + while(*At && isWhitespace(*At)) + At++; + return At; +} + +bool isDigit(char Digit) +{ + return (Digit >= '0' && Digit <= '9'); +} + +int isNumber(char *Number) +{ + int Result = 0; + while(*Number && *Number != ' ') + { + if(!isDigit(*Number)) + { + Result = -1; + return Result; + } + Number++; + Result++; + } + + return Result; +} + +int main(int argc, char **argv) +{ + stack Stack = {}; + float Result = 0; + // + // Parsing + // + //char *Input = "6 3 + 4 - 20 *"; + char *Input = argv[1]; + char *At = Input; + while(*At) + { + At = eatAllWhitespaces(At); + switch(*At) + { + case '+': + { + float Addent1 = pop(&Stack); + float Addent2 = pop(&Stack); + push(&Stack, Addent1 + Addent2); + }break; + case '-': + { + float Subtrahend = pop(&Stack); + float Minuend = pop(&Stack); + + push(&Stack, Minuend - Subtrahend); + }break; + case '*': + { + float Multiplicand = pop(&Stack); + float Multiplier = pop(&Stack); + push(&Stack, Multiplier * Multiplicand); + }break; + case '/': + { + float divisor = pop(&Stack); + float dividend = pop(&Stack); + push(&Stack, dividend / divisor); + }break; + default: + { + int Length = isNumber(At); + if(Length != -1) + { + push(&Stack, atof(At)); + At += Length -1; + } + else + { + printf("ERROR: Only Numbers and Operators + - * and / are allowed"); + } + } + } + At++; + } + while(peak(&Stack)) + { + printf("%f ", pop(&Stack)); + } + printf("\n"); +} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/stack.h b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/stack.h new file mode 100644 index 0000000..94674ba --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/stack.h @@ -0,0 +1,44 @@ +#include + +typedef struct node +{ + float Value; + struct node *Next; +}node; + +typedef struct +{ + node *Top; +}stack; + +node *alloc_node(float Value, node *Next) +{ + node *NewNode = malloc(sizeof(node)); + NewNode->Value = Value; + NewNode->Next = Next; + + return NewNode; +} + +void push(stack *Stack, float Value) +{ + // TODO: implement this + node *NewNode = alloc_node(Value, Stack->Top); + Stack->Top = NewNode; +} + +float pop(stack *Stack) +{ + // TODO: implement this + float Result = Stack->Top->Value; + node *Top = Stack->Top->Next; + free(Stack->Top); + Stack->Top = Top; + return Result; +} + +node *peak(stack *Stack) +{ + // TODO: implement this + return Stack->Top; +} diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/term_generator.sh b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/term_generator.sh new file mode 100755 index 0000000..f216652 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/term_generator.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +generating=true +number_count=0 +arguments="" +last_number=0 + +#number 1 +number_count=$((number_count+1)) +number=$(((RANDOM % 100)+1)) +arguments="$arguments $number" +last_number=$number + +#number 2 +number_count=$((number_count+1)) +number=$(((RANDOM % 100)+1)) +arguments="$arguments $number" +last_number=$number + +while [ "$generating" = "true" ] +do + if [ $number_count -ge 2 ] + then + choice=$((RANDOM % 2)) + if [ $choice = 0 ] + then + #operator + operator=$((RANDOM % 4)) + if [ $operator = 0 ] + then + number_count=$((number_count-1)) + arguments="$arguments +" + elif [ $operator = 1 ] + then + number_count=$((number_count-1)) + arguments="$arguments -" + elif [ $operator = 2 ] + then + number_count=$((number_count-1)) + arguments="$arguments *" + elif [ $operator = 3 ] + then + if [ $last_number -ne 0 ] + then + number_count=$((number_count-1)) + arguments="$arguments /" + fi + fi + else + #number + number_count=$((number_count+1)) + number=$(((RANDOM % 100)+1)) + arguments="$arguments $number" + last_number=$number + fi + else + choice=$((RANDOM % 2)) + if [ $choice = 0 ] + then + generating=false + else + #number + number_count=$((number_count+1)) + number=$(((RANDOM % 100)+1)) + arguments="$arguments $number" + last_number=$number + fi + fi +done +echo "$arguments" + + diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/test.sh b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/test.sh new file mode 100755 index 0000000..6850a72 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +arguments=$(./term_generator.sh) + +program_out=$(./program "$arguments") +solution_out=$(./solution "$arguments") + +echo "term: $arguments" + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false +fi + + diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/type b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/02-calculator/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-advanced/sections/02-basic-algorithms/section b/oer/courses/c-advanced/sections/02-basic-algorithms/section new file mode 100644 index 0000000..2d0f317 --- /dev/null +++ b/oer/courses/c-advanced/sections/02-basic-algorithms/section @@ -0,0 +1 @@ +{"title": "Example Algorithms", "description": "Implement algorithms, which use the data-structures from the previous section "} diff --git a/oer/courses/c-basics/.gitignore b/oer/courses/c-basics/.gitignore new file mode 100644 index 0000000..cec1700 --- /dev/null +++ b/oer/courses/c-basics/.gitignore @@ -0,0 +1,3 @@ +*.pyc +__pycache__ +program diff --git a/oer/courses/c-basics/meta b/oer/courses/c-basics/meta new file mode 100644 index 0000000..e1eea61 --- /dev/null +++ b/oer/courses/c-basics/meta @@ -0,0 +1 @@ +{"title": "C Basics", "description": "A introduction to the C programming language. Whenever performance matters and you are working close with the operating system knowledge in C is inevitable."} diff --git a/oer/courses/c-basics/sections/01-introduction/00-weclome/content.html b/oer/courses/c-basics/sections/01-introduction/00-weclome/content.html new file mode 100644 index 0000000..c8b2bab --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/00-weclome/content.html @@ -0,0 +1,11 @@ +

+ Welcome to the introductory course for learning the C programming language. + This course is for people, who do have some experience in programming. + You will be provided with task to train interactively and will get + information on how C works and how you program in it. +

+

+ The beginning of the course covers basics, like what is a compiler, what are expressions + and all the fundamental syntax. From there, we will tackle the daunting topic of + pointers and will move on to more complex concepts. +

diff --git a/oer/courses/c-basics/sections/01-introduction/00-weclome/meta b/oer/courses/c-basics/sections/01-introduction/00-weclome/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/00-weclome/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/c-basics/sections/01-introduction/00-weclome/type b/oer/courses/c-basics/sections/01-introduction/00-weclome/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/00-weclome/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/Makefile b/oer/courses/c-basics/sections/01-introduction/01-c-hello/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/content.html b/oer/courses/c-basics/sections/01-introduction/01-c-hello/content.html new file mode 100644 index 0000000..9bd1a4d --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/content.html @@ -0,0 +1,24 @@ +

+ Welcome to the first lecture. This is what you will see most of the time. + A text in the beginning, explaining all the things you need to know for the lecture and what you have to do, + then a text-editor, where you supposed to edit the code to complete the given task and three buttons below the editor. The execute Button will compile + and execute your code, the submit button will do the same and also check, if your solution is correct. If your solution was correct, you can press the + continue button to go to the next lecture. +

+

+ Now back to the lecture. This is probably the most simple program. That is why you find it in almost any basic programming book or tutorial. + Ignore for now the #include <stdio.h>. It is not important for now. Below that you see the main-function. + It marks the entriepoint for your program. + From there on the computer will exactly execute what you write in order (with exceptions we won't go into). That is what is commonly know as imperative programming. +

+

+ The first thing in our program is a comment and is initiated by double slashes "//". Everything after that in the same line will be ignored by the compiler and therefore not be executed. + For longer comments you can also surround it by "/* */" so you don't have to type double slashes in every line. +

+

+ So now to the exciting part. The line:
+ printf("Hello User!");
+ will write text to the console. In this case Hello User!. Every statement in C ends with a semicolon ";". + Your task will be to experiment with that line. Change the program to print out Hello World!. +

+ diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/meta b/oer/courses/c-basics/sections/01-introduction/01-c-hello/meta new file mode 100644 index 0000000..210a30b --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/meta @@ -0,0 +1 @@ +{"title": "Hello World!"} diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/program.c b/oer/courses/c-basics/sections/01-introduction/01-c-hello/program.c new file mode 100644 index 0000000..c818606 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/program.c @@ -0,0 +1,9 @@ +#include // Ignore this + +int main(int argc, const char *argv[]) // the main function is the entrypoint to your program +{ + // TODO: use printf() to print "Hello World!" on the display. + printf("Hello User!"); + + return 0; // Ignore this +} diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/regex b/oer/courses/c-basics/sections/01-introduction/01-c-hello/regex new file mode 100644 index 0000000..4391264 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/regex @@ -0,0 +1 @@ +^Hello World!$ diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/solution.c b/oer/courses/c-basics/sections/01-introduction/01-c-hello/solution.c new file mode 100644 index 0000000..17c132c --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/solution.c @@ -0,0 +1,8 @@ +#include + +int main(int argc, const char *argv[]) +{ + // TODO: use printf() to print "Hello World!" on the display. + printf("Hello World!"); + return 0; +} diff --git a/oer/courses/c-basics/sections/01-introduction/01-c-hello/type b/oer/courses/c-basics/sections/01-introduction/01-c-hello/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/01-c-hello/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/01-introduction/02-compiler/content.html b/oer/courses/c-basics/sections/01-introduction/02-compiler/content.html new file mode 100644 index 0000000..b87d55e --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/02-compiler/content.html @@ -0,0 +1,31 @@ +

+ You may have heard, that C is a compiled language. But what does that mean? + Basically programming languages can be categorized into two classes. Compiled and Interpreted. + An interpreted language will be interpreted at run time by another program, which will then send the necessary commands to the CPU to do, what you specified. + Examples for that, are languages like Python and Perl.
+ C on the other hand is a compiled language. That means we have a program, the compiler, which turns your code into executable binaries. + These can be run directly by the CPU without any overhead. +

+ +

+ A compiler consist of multiple stages. First comes the lexer. It turns all the meaningless characters into tokens, + which have meaning to the compiler. Then these tokens get parsed, to build the syntax-tree. + With the syntax-tree the compiler can start code generation. This code can then be optimized by the optimizer, + if you choose so. Bare in mind, that optimized code can be harder to debug. +

+ +

+ On top of that C has the preprocessor. It touches the code before the compiler gets it. It is used for macros, + including header-files and other stuff to prepare your code for compilation. +

+ +

+ In this course you will not see the compiler, because we want you to concentrate on learning C. + But if you are done with all the lectures, you should download one of the many compilers. + We are using GCC and compiling for the c99 standard. But feel free to experiment with other compilers like Clang. +

+

+ A simple compile command in a command line with gcc could look like this:
+ gcc -std=c99 -o <program_name> <source_code_file>.c + For further information read the GCC-Documentation. +

diff --git a/oer/courses/c-basics/sections/01-introduction/02-compiler/meta b/oer/courses/c-basics/sections/01-introduction/02-compiler/meta new file mode 100644 index 0000000..b761f3c --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/02-compiler/meta @@ -0,0 +1 @@ +{"title": "Compilers"} diff --git a/oer/courses/c-basics/sections/01-introduction/02-compiler/type b/oer/courses/c-basics/sections/01-introduction/02-compiler/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/02-compiler/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/Makefile b/oer/courses/c-basics/sections/01-introduction/03-assembly/Makefile new file mode 100644 index 0000000..617484d --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/Makefile @@ -0,0 +1,10 @@ + +all: + cp -f program.c program.S + gcc -c program.S -o program.o + gcc program.o -o program + +clean: + rm -f program + rm -f program.o + rm -f program.S diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/content.html b/oer/courses/c-basics/sections/01-introduction/03-assembly/content.html new file mode 100644 index 0000000..96bbcde --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/content.html @@ -0,0 +1,20 @@ +

+ Assembly-Language is the most basic form of programming languages. Normally every line of assembly stands for one CPU-instruction. + Luckily most people don't program in assembly anymore, because it is hard to understand. Only a few people program part of their programs in it, + if they need that extra bit of control, to get that last bit of performance out of that code. +

+

+ Nevertheless it is a very useful tool, to be able to understand assembly. Sometimes you just don't understand, why your code is slow or buggy and you want to know, + what the compiler did. Then you can put your code in a disassembler to basically turn machine code into assembly and see exactly what your code is doing. +

+

+ We will only give you a brief introduction to assembly. But if you are interested or serious about low-level programming you should definitely take a look + at the + Intel 64 and IA-32 Architectures Software Developer's Manual and some tutorials on assembly.
+ The following code is the disassembly of the Hello World Program. It may look daunting at first, but it is actually not that hard to understand. + Lines with periods are commands to the assembler, words with colon at the end are labels and the rest are assembly instructions, which are usually a one to one mapping + to CPU instructions. Please take your time to understand the code. +

+

+ Your task is to change the output of this program to print out Hello <your name>. +

diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/meta b/oer/courses/c-basics/sections/01-introduction/03-assembly/meta new file mode 100644 index 0000000..789f403 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/meta @@ -0,0 +1 @@ +{"title": "Assembly"} diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/program.c b/oer/courses/c-basics/sections/01-introduction/03-assembly/program.c new file mode 100644 index 0000000..32b1f4c --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/program.c @@ -0,0 +1,24 @@ + .file "assembly.c" # information for the debugger + .section .rodata # declares read only section +.LC0: + .string "Hello World!" # the Hello World! string we want to print + .text + .globl main # defines main as a global label for the linker + .type main, @function # declares main as a function +main: + pushq %rbp # function prologue + movq %rsp, %rbp + leaq -4144(%rsp), %rsp + orq $0, (%rsp) + leaq 4128(%rsp), %rsp + movl %edi, -4(%rbp) + movq %rsi, -16(%rbp) + leaq .LC0(%rip), %rdi # load hello world! string + movl $0, %eax + call printf@PLT # call printf + movl $0, %eax + leave + ret # return from the program + .size main, .-main # some information + .ident "GCC: (GNU) 6.2.1 20160830" + .section .note.GNU-stack,"",@progbits diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/regex b/oer/courses/c-basics/sections/01-introduction/03-assembly/regex new file mode 100644 index 0000000..4efba8a --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/regex @@ -0,0 +1 @@ +^Hello .*!*(? + +int main(int argc, const char *argv[]) +{ + // TODO: use printf() to print "Hello World!" on the display. + printf("Hello World!"); + return 0; +} diff --git a/oer/courses/c-basics/sections/01-introduction/03-assembly/type b/oer/courses/c-basics/sections/01-introduction/03-assembly/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03-assembly/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/Makefile b/oer/courses/c-basics/sections/01-introduction/03.5-printf/Makefile new file mode 100644 index 0000000..7e4d94b --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program -lm + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/content.md b/oer/courses/c-basics/sections/01-introduction/03.5-printf/content.md new file mode 100644 index 0000000..a7667a9 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/content.md @@ -0,0 +1,14 @@ +The function ``printf`` is the standard way in C to write something to the standard output. +You can just print out a string, but more often then not you want to augment your string with text or numbers determine at runtime. + +For that printf has placeholders. When you write % into your string, printf expects you to pass in an argument, to replace the %. +Unfortunately writing % isn't enough you also have to specify the type of the argument. To tell printf what kind of argument to expect, +you have to write a letter after the %. + +* s for an nullterminated string. If it is not nullterminated your program could crash. +* c for a single character +* d for an signed integer +* u for an unsigned integer +* f for floating point numbers + +This is not a complete list. You also can specify some formatting options. If you are on a linux system you can use __man printf__ to get all the options or you can simply use google. \ No newline at end of file diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/meta b/oer/courses/c-basics/sections/01-introduction/03.5-printf/meta new file mode 100644 index 0000000..2b61321 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/meta @@ -0,0 +1 @@ +{"title": "Printf"} diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/program.c b/oer/courses/c-basics/sections/01-introduction/03.5-printf/program.c new file mode 100644 index 0000000..4c47422 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/program.c @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, char **argv) +{ + // TODO: calculate the hypotenuse of the triangle a=9 b=15 c=? + // using the pythagorean theorem. + // to do that, you need to use sqrt(n) from the math.h lib, to calculate the square-root + printf("The hypotenuse of the triangle is: %f", 0.0f /* TODO: replace the 0 with your calculation*/); + + // if you want to try even more of the math library, try using + // pow(a,b) instead of the *-operator. + // a is the base and b is the power. +} diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/regex b/oer/courses/c-basics/sections/01-introduction/03.5-printf/regex new file mode 100644 index 0000000..e2dbf56 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/regex @@ -0,0 +1 @@ +^\s*The hypotenuse of the triangle is: 17.492856\s*$ diff --git a/oer/courses/c-basics/sections/01-introduction/03.5-printf/type b/oer/courses/c-basics/sections/01-introduction/03.5-printf/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/03.5-printf/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/Makefile b/oer/courses/c-basics/sections/01-introduction/04-libraries/Makefile new file mode 100644 index 0000000..7e4d94b --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program -lm + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/content.html b/oer/courses/c-basics/sections/01-introduction/04-libraries/content.html new file mode 100644 index 0000000..1460cb3 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/content.html @@ -0,0 +1,20 @@ +

+ Remember the line from the hello world program #include <stdio.h>? + This is a instruction for the preprocessor to include a library to your code. + More specifically the standard library stdio.h. Libraries are a set of functions + and data structure you can use to make your live easier. + They are tested and optimized but more importantly; You don't have to write + everything by hand. +

+

+ We talk about functions and data structures later. All you need to know is, + that they are like complex instruction you can call. Like the printf function we were using + in the beginning. Printf is a function that takes a string with placeholders, which specify the format + (hence the name printf print formated), and the inputs for the placeholders. With that it builds the final string + and prints it out to the standard output. +

+

+ There are many useful libraries you can use. The standard libraries every compiler has to provide, 3rd party libraries you + can download or libraries you can write your self to reuse them later. + We will use the math.h library in this example. +

diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/meta b/oer/courses/c-basics/sections/01-introduction/04-libraries/meta new file mode 100644 index 0000000..c962b0d --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/meta @@ -0,0 +1 @@ +{"title": "Libraries"} diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/program.c b/oer/courses/c-basics/sections/01-introduction/04-libraries/program.c new file mode 100644 index 0000000..4c47422 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/program.c @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, char **argv) +{ + // TODO: calculate the hypotenuse of the triangle a=9 b=15 c=? + // using the pythagorean theorem. + // to do that, you need to use sqrt(n) from the math.h lib, to calculate the square-root + printf("The hypotenuse of the triangle is: %f", 0.0f /* TODO: replace the 0 with your calculation*/); + + // if you want to try even more of the math library, try using + // pow(a,b) instead of the *-operator. + // a is the base and b is the power. +} diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/regex b/oer/courses/c-basics/sections/01-introduction/04-libraries/regex new file mode 100644 index 0000000..e2dbf56 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/regex @@ -0,0 +1 @@ +^\s*The hypotenuse of the triangle is: 17.492856\s*$ diff --git a/oer/courses/c-basics/sections/01-introduction/04-libraries/type b/oer/courses/c-basics/sections/01-introduction/04-libraries/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/04-libraries/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/Makefile b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/content.html b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/content.html new file mode 100644 index 0000000..2fbb0c2 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/content.html @@ -0,0 +1,23 @@ +

+ In the last lecture we used the preprocessor to include a library. But it can do + more stuff than just include files. The preprocessor, as the name suggest, runs + before the compiler and does some initial work. It includes the files, expands macros, + gives you compile time information and provides you if conditional compilation. + Preprocessor directives always start with #. +

+

+ Some of its features should be used with great care. Macros are very powerful, + but they aren't type checked and are hard to debug. + Conditional compilation is useful to define debug only features or define + platform-agnostic macros, but they also can make your code harder to read. + For now we just take a look at macros. In a later part of the course we will revisit this topic. +

+

+ A macro is something that the preprocessor will replace with what ever you specify. + To define a macro you simply write #define then the name of the macro with optional + parameters in parentheses and then what you want your macro to expand to. + If your macro expands to another macro, then this process starts again. +

+

+ Your task is to find the error in the Square macro and define a macro yourself. +

diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/meta b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/meta new file mode 100644 index 0000000..6c3f450 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/meta @@ -0,0 +1 @@ +{"title": "Preprocessor"} diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/program.c b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/program.c new file mode 100644 index 0000000..02bca1d --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/program.c @@ -0,0 +1,23 @@ +#include +#include + +// Here we define a simple macro +#define PI 3.14159265359f + +// Another macro with parameters +// TODO: Fix the problem with this macro +#define Square(x) (x*x) + +// TODO: define a macro that doubles the value of an variable. + +int main(int argc, char **argv) +{ + float pisqr = Square(PI); + printf("Pi to the power of 2 is equal to %f\n",pisqr); + + int value = Square(1+2); + printf("3 squared is %d\n", value); + + // TODO: call your double macro on value + printf("3 squared doubled is %d", value); +} diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/regex b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/regex new file mode 100644 index 0000000..02ca902 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/regex @@ -0,0 +1 @@ +^\s*Pi to the power of 2 is equal to 9.869605\s*3 squared is 9\s*3 squared doubled is 18\s*$ diff --git a/oer/courses/c-basics/sections/01-introduction/05-preprocessor/type b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/05-preprocessor/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/choices b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/choices new file mode 100644 index 0000000..6494267 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/choices @@ -0,0 +1,4 @@ +It interprets the code on the fly, to tell the CPU what to do. +*It translates the code into a CPU executable binary. +It prepares the code for further processing. +It helps you, to write the code. diff --git a/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/meta b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/meta new file mode 100644 index 0000000..3a423e2 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/meta @@ -0,0 +1 @@ +{"title": "Quiz-Compiler", "choose": "one"} diff --git a/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/question b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/question new file mode 100644 index 0000000..47fef7b --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/question @@ -0,0 +1 @@ +What does the compiler do? diff --git a/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/type b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/06-quiz-compiler/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/c-basics/sections/01-introduction/section b/oer/courses/c-basics/sections/01-introduction/section new file mode 100644 index 0000000..bab5de8 --- /dev/null +++ b/oer/courses/c-basics/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Introduction", "description": "The very basics."} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/content.html b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/content.html new file mode 100644 index 0000000..483257e --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/content.html @@ -0,0 +1,12 @@ +

+ Expressions in c are basically the building blocks of statements, which them self are used to build your program. + The most simple expressions are just values, variables or even functions. You can chain these simple expressions to + even bigger expressions with operators. The semicolon at the end turns it into a statement. +

+

+ C has many different operators. Arithmetic ones like + and -, boolean logic like && and ||, + bit-wise logic and shifts like & or <<, assignment = and many more. Here is a list of all the operators. +

+

+ Try out some operators to build expressions and see how they effect the evaluated output. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/meta b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/meta new file mode 100644 index 0000000..cadd78d --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/meta @@ -0,0 +1 @@ +{"title": "Expressions"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/program.c b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/program.c new file mode 100644 index 0000000..4f4e935 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/program.c @@ -0,0 +1,22 @@ +#include + +int main(int argc, const char *argv[]) +{ + // we prepared the printf function, so it will print a number, which we pass behind the string + printf("%d\n", (10*5)/7+1); + // instead of a number we passed a more complex expression with some operators. + // execute the program and see what it evaluated to. + + // TODO: change the expression to print out 42 using some operators + printf("%d", 5+5); + + // You can also just write expression. They will be evaluated, but + // because we are not using them, they are useless + 5; // This is an expression. + 3+6; // This is also an expression. It will evaluate to 9. + + !(5+6 > (4*5-1)); // You can build long expressions. + // later we will safe these values in variables or will pass them to other function. + + return 0; +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/regex b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/regex new file mode 100644 index 0000000..777110d --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/regex @@ -0,0 +1 @@ +^(.|\s)*42$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/type b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/00-expressions/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/content.html b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/content.html new file mode 100644 index 0000000..1ef33b7 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/content.html @@ -0,0 +1,17 @@ +

+ Variables are used to store values. Basically you have a storage location with a name and an associated type. + The compiler will check, if the value you assign to the variable is from the same type as the variable. + If not, it will throw an error. +

+

+ That is because C is a statically type checked language. Dynamically type checked languages may let you use your variables more freely, + but will also hide bugs, which can produce unpredictable results. It is a small price to pay, to + build a more robust code, which is immune to this kind of bugs, if you don't miss use type casting. +

+

+ Because variables just refer to a space in memory, you can easily change the value to a new one. + The thing that you can't change is the type. + Sometimes you just want to have a name for a constant value. In C you can use the const keyword to declare + a variable as constant, i.e you cant change the value once it is assigned. + If you know the value isn't supposed to change, you should declare it const to prevent bugs, which you could be a pain to find. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/meta b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/meta new file mode 100644 index 0000000..e1ada9b --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/meta @@ -0,0 +1 @@ +{"title": "Variables"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/program.c b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/program.c new file mode 100644 index 0000000..110dc7c --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/program.c @@ -0,0 +1,33 @@ +#include + +int main(int argc, const char *argv[]) +{ + // To declare a variable you first specify the type and then the identifier. + int value; // int stands for integer + + // you can the use the assignement operator to assign a value to the variable. + value = 42; + + // some times you want to assign a value right when you declare the variable. + int value2 = 3+5; + + printf("Value: %d \n", value); // you can use a variable instead of a value + + const int constant = 10; + // TODO: uncommend the next line and see what happends + // constant = 22; + + + // if you want to assign a new value, you can just use the assignement operator again + value = value2; + + printf("Value: %d \n", value); + + // you can also assign more complex expressions + value = ((3+5)*4+5+6)%3; + + // TODO: declare your own variable and asign the variable constant to it + printf("Task %d", 0/*TODO: repace the o with your variable*/); + + return 0; +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/regex b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/regex new file mode 100644 index 0000000..afb642b --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/regex @@ -0,0 +1 @@ +^(.|\s)*10\s*$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/01-variables/type b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/01-variables/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/02-types/Makefile new file mode 100644 index 0000000..86201b1 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/Makefile @@ -0,0 +1,5 @@ +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/content.html b/oer/courses/c-basics/sections/02-basic-language-features/02-types/content.html new file mode 100644 index 0000000..d49df5a --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/content.html @@ -0,0 +1,85 @@ + + +

+ There are only two major classes of types in C. Integer types and real/floating point number types. + Everything else derives from them. Characters are just 8 bit integer numbers which use ASCII encoding. + Boolean values are also just integers. 0 is False and everything else is True. + You can also define your own data-structures and use them as types. More on that in a later section. +

+

+ Here is a table of all the basic types in c with their bit sizes. The standard doesn't define all sizes exactly. + So be care full. They can change from platform to platform or from compiler to compiler. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeType nameGuaranteed Bit SizeCommon Bit SizeRange
I
n
t
e
g
e
r
s
char8 bits8 bits0-255
shortat least 16 bits16 bits0-65535
intat least 16 bits32 bits0-4294967295
longat least 32 bits64 bits0-18446744073709551615
long longat least 64 bits64 bits0-18446744073709551615
R
e
a
l

N
u
m
b
e
r
s
float32 bits32 bits1.17549x10-38-3.40282x1038
double64 bits64 bits2.22507x10-308-1.79769308
+
+

+

+ With the keyword unsigned you specify that you only want to use positive numbers. That gives you a bigger positive range, but you wont be able + to use negative numbers. The keyword signed does the opposite. It specifies that you also want to encode negative numbers. This shrinks + your positive range, but you can use negative numbers.
+ For example a unsigned char can store values between the numbers 0 and 255. The signed char stores values between -128 to 127. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/meta b/oer/courses/c-basics/sections/02-basic-language-features/02-types/meta new file mode 100644 index 0000000..afaadb8 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/meta @@ -0,0 +1 @@ +{"title": "Types"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/program.c b/oer/courses/c-basics/sections/02-basic-language-features/02-types/program.c new file mode 100644 index 0000000..e51b55b --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/program.c @@ -0,0 +1,48 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + unsigned char foo = 100; // Here we declared a variable from type char and assigned the value 100. + printf("foo: %d\n", foo); + + foo += 100; // += is the same as writing foo = foo + 100; + // When we print this out it should say foo: 200 + printf("foo: %d\n", foo); + + foo += 100; + // Now see what happens when we print out foo again + printf("foo: %d\n", foo); + // This is called an overflow. The types wasn't big enough to hold 300 so it wrapped around. + + // remember when you declare an integer as signed the positive range shrinks + signed char bar = 200; + printf("bar: %d\n", bar); + + // Char is also the datatype used for characters. + // You can tell printf to interpret foo as a character, + // if you write %c instead %d as the formatting + printf("foo: %c\n",foo); + + // if you want to assign the ASCII value of a character to a variable + // just write it in '' + foo = 'a'; + + // You should choose your types carefully. + // Here we want to divide to numbers + + int Divident = 1; + int Divisor = 2; + + int Result = Divident/Divisor; + + // Look at the result. + printf("Result = %d\n", Result); + // TODO: fix the division, such that the correct result is being displayed + // TIP: %f is used to print out floating point values + + // Integers can't represent real numbers. + // But don't presume floats can represent every number. + // as the numbers get smaller or bigger you get less precision + // and your numbers get rounded to the next represented number. +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/regex b/oer/courses/c-basics/sections/02-basic-language-features/02-types/regex new file mode 100644 index 0000000..5d12332 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/regex @@ -0,0 +1,2 @@ + +^(\s|.)*\s*Result = 0.50*\s*$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/02-types/type b/oer/courses/c-basics/sections/02-basic-language-features/02-types/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/02-types/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/Makefile new file mode 100644 index 0000000..48e6ac3 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/content.html b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/content.html new file mode 100644 index 0000000..d3956b7 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/content.html @@ -0,0 +1,27 @@ +

+ Almost every program or algorithm needs some kind of conditional branching. It is used to control the flow of your program. + The most common form in any programming language is the if-statement or sometimes called if-then-else-statement. + It is used to define parts of your code, which are only executed, if certain conditions are met. +

+

+ The if-statement consist of the keyword if, followed by an expression and then followed by a statement. + The statement can be a normal statement as seen before or more commonly a block statement, which is just a group of statements treated as one. They are opened and closed by curly braces. + If you want to define behavior, for when the condition is not met, you follow your if-statement up with an else-statement. +

+

+ The if-statement works by evaluating the expression. If it is true, it will execute the following statement, if not, it will jump over + it to the next statement. +

+

+ Because C has no boolean values by default, any non zero value will be interpreted as true and all zeros to false. + This can be useful. E.g if you want to check for null-pointers, you only have to put the pointer into the statement. + But it can be dangerous to. The compiler won't warn you, if you forget to use any boolean operators. +

+

+ Normally you form your expression with boolean operators(==,!=,<,>,<=,>=) + and logical operators (!,&&,||). But as mentioned before you don't have to use them. + Sometimes it is easier and shorter to use the fact that any non zero value is true. +

+

+ Read trough the following examples and do the comparison task in the end of the file. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/execute.sh b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/execute.sh new file mode 100755 index 0000000..2daecdb --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/execute.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +for (( i = 0; i < 1; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % 9 ) + 1)) + + ./program $a $b +done diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/meta b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/meta new file mode 100644 index 0000000..40b17ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/meta @@ -0,0 +1 @@ +{"title": "If-Statements"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/program.c b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/program.c new file mode 100644 index 0000000..58f0546 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/program.c @@ -0,0 +1,68 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + int value = 42; + + if (value >= 27) + { + // This part of the program is only executed, if the expression is true + printf("value is indeed bigger or equal to 27 \n"); + } + + // the else-statement will be executed if the if-statement wasn't true + if (value == 43) + { + // This will not be executed + printf("value is equal 43 \n"); + } + else + { + // This part will be executed + printf("value is not equal to 43 \n"); + } + + // Another useful syntax is else if statement. + // You want to use it if you want to test for multiple things. + // But be careful! The first condition, which is true, gets executed. + if(value != 42) + { + // This will not be executed + printf("value is not equal to 42 \n"); + } + else if(value < 45) + { + // This will be executed + printf("value is less than 45 \n"); + } + else if( value == 42) + { + // This will not be executed + printf("value is equal to 42\n"); + } + + // You can also chain expressions together with the logical operators like && for and || for or and ! for not + if(!(value >= 0 && value <42)) + { + printf("Value is not bigger or equal to 0 and less than 42\n"); + } + + // in c any value other then 0 is considered to be true + // even negative values are true + if(value) + { + // this is legal in c and will be considered as true + } + // this is a great way to check for null-pointers + + int Value1 = atoi(argv[1]); + int Value2 = atoi(argv[2]); + // We prepared the variables Value1 and Value2 to hold values, + // which are passed to the program + + // TODO: compare these to values the following way + // if value1 is bigger write to the standart output "value 1 is bigger" + // if value2 is bigger write to the standart output "value 2 is bigger" + // otherwise print out "value 1 is equal to value 2" +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/solution.c b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/solution.c new file mode 100644 index 0000000..80d6ab2 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/03-conditionals/solution.c @@ -0,0 +1,77 @@ +int main(int argc, const char *argv[]) +{ + int value = 42; + + if (value >= 27) + { + // This part of the program is only executed, if the expression is true + printf("value is indeed bigger or equal to 27 \n"); + } + + // the else-statement will be executed if the if-statement wasn't true + if (value == 43) + { + // This will not be executed + printf("value is equal 43 \n"); + } + else + { + // This part will be executed + printf("value is not equal to 43 \n"); + } + + // Another useful syntax is else if statement. + // You want to use it if you want to test for multiple things. + // But be care full! the first condition, which is true gets executed. + if(value != 42) + { + // This will not be executed + printf("value is not equal to 42 \n"); + } + else if(value < 45) + { + // This will be executed + printf("value is less than 45 \n"); + } + else if( value == 42) + { + // This will not be executed + printf("value is equal to 42\n"); + } + + // You can also chain expressions together with the logical operators like && for and || for or and ! for not + if(!(value >= 0 && value <42)) + { + printf("Value is not bigger or equal to 0 and less than 42\n"); + } + + // in c any value other then 0 is considered to be true + // even negative values are true + if(value) + { + // this is legal in c and will be considered as true + } + // this is a great way to check for null-pointers + + int Value1 = atoi(argv[1]); + int Value2 = atoi(argv[2]); + // We prepared the variables Value1 and Value2 to hold values, + // which are passed to the program + + // TODO: compare these to values the following way + // if value1 is bigger write to the standart output "value 1 is bigger" + // if value2 is bigger write to the standart output "value 2 is bigger" + // otherwise print out "value 1 is equal to value 2" + if(Value1>Value2) + { + printf("value 1 is bigger"); + } + else if(Value1 + Usually algorithms need a way to express iteration, doing somethings multiple times until a condition is met. + In C we have 3 basic types of loops to achieve that. The for-loop, the while loop and the do-while loop. +

+

+ The for-loop consist of the keyword for, followed by 3 expressions and then the statement or block, which should be iterated over. + The first expression is for the initialization. It will only be executed in the beginning. The second one is for the conditional check. + Only if it is evaluated to true, the code will be iterated over. This statement will be checked each time at the beginning of the loop. + The last expression is for everything, which needs to be done after one iteration. Usually the for-loop is used for counted-looping + in combination with a loop counter. But you can use them differently. E.g to iterate over a linked list. +

+

+ The while loop consist of the keyword while followed by an expression for the conditional check and then by the statement or a block. + The while loop will first check, if the expression will evaluate to true. If that is the case, it will execute the code and check again until the + expression is false. +

+

+ The do-while-loop works just like the while-loop, except that it will check the expression at the end of every iteration. + That's why the do-while-loop consist of the do keyword, then the statement or block and then the while keyword + with the expression for the conditional check. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/04-loops/meta b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/meta new file mode 100644 index 0000000..713d650 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/meta @@ -0,0 +1 @@ +{"title": "Loops"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/04-loops/program.c b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/program.c new file mode 100644 index 0000000..7d3b3e7 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/program.c @@ -0,0 +1,39 @@ +#include + +int main(int argc, const char *argv[]) +{ + // There are 3 basic types of loops + int i = 0; + + // In the while loop the condition is checked before each execution + // on true the block is executed + // As a result the block is executed as long as the condition is met + while (i < 10) + { // condition i < 10 + i++; // increment i + } + + // The do while loop works similarly to the while loop. + // But the block is executed at least once. + // Since the condition is only checked after the first execution. + do { + i++; + } while (i < 20); + + // for loops provide an easy shorthand way to define conditions + for (int j = 0; j < 20; j += 5) + { + // continue skips the current iteration + // subsequent iterations may work as normal. + continue; + printf("This is never reached."); + } + + for (;;) + { + // Break exits any loop for good + break; + } + + // TODO: print the numbers 1 to 10 using a for loop. +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/04-loops/regex b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/regex new file mode 100644 index 0000000..9faf8ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/regex @@ -0,0 +1 @@ +^\s*1.*10\s*$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/04-loops/solution b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/solution new file mode 100644 index 0000000..583010b --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/solution @@ -0,0 +1 @@ +# may hold required skills how to reference these in a comprehensive way remains for disussion diff --git a/oer/courses/c-basics/sections/02-basic-language-features/04-loops/type b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/04-loops/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/Makefile new file mode 100644 index 0000000..86201b1 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/Makefile @@ -0,0 +1,5 @@ +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/content.html b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/content.html new file mode 100644 index 0000000..7c8ba15 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/content.html @@ -0,0 +1,10 @@ +

+ More often then not you need to talk about more than one + variable, a collection of data. The most simple construct to do that + is the array. The data is stored consecutively as a block. + The array is also the list data-structure with the least overhead concerning the access and is the only list data-structure, which is supported without any libraries. +

+

+ To access an member of the array you use the subscript operator []. + In C arrays starts at index 0 and ends at index n-1, where n is the number of members. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/meta b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/meta new file mode 100644 index 0000000..1a9dd72 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/meta @@ -0,0 +1 @@ +{"title": "Arrays"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/program.c b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/program.c new file mode 100644 index 0000000..7645aa6 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/program.c @@ -0,0 +1,28 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + // You declare a array by simply putting [] behind your variable. + int Numbers[5]; + + // In c the first element in the array has the index 0. + // So to access the last one you have to subtract one from the element count. + // TODO: use the []-operator to fill out the rest of the array with the numbers 1 - 5 + Numbers[0] = 1; + + // TODO: now use the Numbers from the array and square them. After that write them back into the array. + + // If you want to calculate the element count of a array + // you can use this line of code: + int count = sizeof(Numbers)/sizeof(Numbers[0]); + // Printing the array + for(int i = 0; i < count; i++) + { + printf("%d ", Numbers[i]); + } + + // you can also have multidimensional arrays. + // you simply add more [] + // Example: int 3D_Matrix[10][10][10]; +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/regex b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/regex new file mode 100644 index 0000000..3884bfa --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/regex @@ -0,0 +1 @@ +^\s*1 4 9 16 25\s*$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/type b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-arrays/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/Makefile new file mode 100644 index 0000000..f6f16c4 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/content.html b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/content.html new file mode 100644 index 0000000..be8eaad --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/content.html @@ -0,0 +1,7 @@ +

+ Like If-Statements Switch-Statements are used to control the flow + of your program. They are often used, if there are many different + cases to account for. Sometimes Switch-Statements can be faster, + because the compiler can try to optimize the code with binary search or + jump tables. However it is not guaranteed that these techniques work on your code. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/meta b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/meta new file mode 100644 index 0000000..6e4b694 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/meta @@ -0,0 +1 @@ +{"title": "Switch"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/program.c b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/program.c new file mode 100644 index 0000000..be41445 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/program.c @@ -0,0 +1,27 @@ +#include + +int main(int argc, const char *argv[]) +{ + char String[] = "1453g5a24"; + char *At = String; + while(*At) + { + char c = *At; + // Complete this Switch-Statement to print out the numbers to 5 in words + // Characters should just be printed out as is. (use the default keyword instead of the case keyword) + // Also fix the bug that is already in the code. + + switch(c) // This defines the expression we are going to switch on. + { + case '1': // The case keywords defines the starting point for code execution + { + printf("One "); + } + case '2': + { + printf("Two "); + }break; // The break stops the program to execute the next case + } + At++; + } +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/regex b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/regex new file mode 100644 index 0000000..5157d21 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/regex @@ -0,0 +1 @@ +^\s*One Four Five Three g Five a Two Four\s*$ diff --git a/oer/courses/c-basics/sections/02-basic-language-features/05-switch/type b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/05-switch/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/Makefile b/oer/courses/c-basics/sections/02-basic-language-features/06-const/Makefile new file mode 100644 index 0000000..a82226f --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/content.html b/oer/courses/c-basics/sections/02-basic-language-features/06-const/content.html new file mode 100644 index 0000000..20da03d --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/content.html @@ -0,0 +1,13 @@ +

+ Const is a way to mark data as constant or in other words read only. + This way, if you try for example to write to a variable, the compiler warns you about it. + So essintualy the compiler helps you find bugs. But it is more than that. + It gives you confidence, that, when you pass pointers to a function (more on that later), + the data wont be changed afterwards. +

+

+ Your task is to first declare the variable pi as constant, since pi should never change and execute. + Then read the error message and correct the mistake. + This may seem silly with so few lines of code, but when you have 1000 of lines of code, it + get harder to find errors like this. +

diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/meta b/oer/courses/c-basics/sections/02-basic-language-features/06-const/meta new file mode 100644 index 0000000..dc7238f --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/meta @@ -0,0 +1 @@ +{"title": "Const"} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/program.c b/oer/courses/c-basics/sections/02-basic-language-features/06-const/program.c new file mode 100644 index 0000000..812f46b --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/program.c @@ -0,0 +1,12 @@ +#include + +int main(int argc, const char *argv[]) +{ + // somewhere in this program is a mistake + float pi = 3.14159265359f; + + float RadiansOfCircle = pi+++pi; + float DegreesOfCircle = RadiansOfCircle*(180.0f/pi); + + printf("A circle has %f degrees", DegreesOfCircle); +} diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/regex b/oer/courses/c-basics/sections/02-basic-language-features/06-const/regex new file mode 100644 index 0000000..aff0280 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/regex @@ -0,0 +1 @@ +^A circle has 2600.0* degrees\s*$ \ No newline at end of file diff --git a/oer/courses/c-basics/sections/02-basic-language-features/06-const/type b/oer/courses/c-basics/sections/02-basic-language-features/06-const/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/06-const/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/02-basic-language-features/section b/oer/courses/c-basics/sections/02-basic-language-features/section new file mode 100644 index 0000000..637a806 --- /dev/null +++ b/oer/courses/c-basics/sections/02-basic-language-features/section @@ -0,0 +1 @@ +{"title": "Basic Language Features", "description": "Features and Syntax"} diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/Makefile b/oer/courses/c-basics/sections/03-functions/07-funktions/Makefile new file mode 100644 index 0000000..2d51e93 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/Makefile @@ -0,0 +1,13 @@ +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution + +test: + ./test.sh + +execute: + ./execute.sh + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/content.html b/oer/courses/c-basics/sections/03-functions/07-funktions/content.html new file mode 100644 index 0000000..c1d229c --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/content.html @@ -0,0 +1,21 @@ +

+ Functions are probably the most powerful construct in programming. They allows you to pull out shared code and reuse + it anytime to reduce typing, reduce bugs and make your code more readable. + It also allows to break down your program in more understandable chunks of code, which you can name. + This highly increases the readability and maintainability of your program. + Last but not least it allows you to use recursion. But more on that later. +

+

+ A function has a return type, a name, parameters and the body. + If the function doesn't return anything, you just write void as the return type. + The name is used to call the function and the parameters define, what arguments you have + to pass to the function and which types they need to be. + The body finally holds the code, which gets executed, when the function gets called. +

+

+ You will probably hear diffident names for what we are calling functions. + The most accurate are procedures ore subroutines. These mean exactly what we described before. + Sometimes you will hear the term method. This is a term from object oriented programming and describes a procedure, which is a member of an object. + The term functions is a little bit overloaded. Normally when it is used, + people talk about procedures but it is also used in the functional programming paradigm. +

diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/execute.sh b/oer/courses/c-basics/sections/03-functions/07-funktions/execute.sh new file mode 100755 index 0000000..743f48f --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/execute.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +for (( i = 0; i < 1; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % a ) + 1)) + c=$(( ( RANDOM % a ) + 1)) + + ./program $a $b $c +done diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/meta b/oer/courses/c-basics/sections/03-functions/07-funktions/meta new file mode 100644 index 0000000..4e12188 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/meta @@ -0,0 +1 @@ +{"title": "Functions"} diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/program.c b/oer/courses/c-basics/sections/03-functions/07-funktions/program.c new file mode 100644 index 0000000..05b4cda --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/program.c @@ -0,0 +1,30 @@ +#include +#include + +// This function should swap two given indices of an given array. +void SwapElements(/*TODO define the parameters*/) +{ + // TODO: write the code to swap to elements +} + +int main(int argc, const char *argv[]) +{ + // These lines turn the arguments from the command-line into ints + // We will talk about command-line parsing later + int ArrayCount = atoi(argv[1]); + int Element1 = atoi(argv[2]); + int Element2 = atoi(argv[3]); + + int Array[ArrayCount]; + + for(int i = 0; i < ArrayCount; i++) + Array[i] = i+1; + + // TODO: uncomment this line + //SwapElements(Array, Element1, Element2); // This calls the function Swap Elements + + for(int i = 0; i < ArrayCount; i++) + printf("Array[%d] = %d\n", i, Array[i]); + + return 0; +} diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/solution.c b/oer/courses/c-basics/sections/03-functions/07-funktions/solution.c new file mode 100644 index 0000000..84a6f61 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/solution.c @@ -0,0 +1,33 @@ +#include +#include + +// This function should swap two givin indecies of an given array. +void SwapElements(int Array[], int a, int b) +{ + int temp = Array[a]; + Array[a] = Array[b]; + Array[b] = temp; + +} + +int main(int argc, const char *argv[]) +{ + // These lines turn the arguments from the commandline into ints + // We will talk about comandline parsing later + int ArrayCount = atoi(argv[1]); + int Element1 = atoi(argv[2]); + int Element2 = atoi(argv[3]); + + int Array[ArrayCount]; + + for(int i = 0; i < ArrayCount; i++) + Array[i] = i+1; + + // TODO: uncommend this line + SwapElements(Array, Element1, Element2); // This calles the funktion Swap Elements + + for(int i = 0; i < ArrayCount; i++) + printf("Array[%d] = %d\n", i, Array[i]); + + return 0; +} diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/test.sh b/oer/courses/c-basics/sections/03-functions/07-funktions/test.sh new file mode 100755 index 0000000..e5182c1 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/test.sh @@ -0,0 +1,31 @@ +#!/bin/bash + + +correct=true + +for (( i = 0; i < 3; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % a ) + 1)) + c=$(( ( RANDOM % a ) + 1)) + + program_out=$(./program $a $b $c) + solution_out=$(./solution $a $b $c) + + if [ "$program_out" == "$solution_out" ] + then + echo "PASS " $program_out " equals " $solution_out + else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false + fi +done + + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/c-basics/sections/03-functions/07-funktions/type b/oer/courses/c-basics/sections/03-functions/07-funktions/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/07-funktions/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/Makefile b/oer/courses/c-basics/sections/03-functions/08-recursion/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/content.html b/oer/courses/c-basics/sections/03-functions/08-recursion/content.html new file mode 100644 index 0000000..63dd114 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/content.html @@ -0,0 +1,29 @@ +

+ Recursion means, that something defines itself by itself. + In maths series like factorial or the Fibonacci series are often defined recursively. + You can also have data structures, which are define recursively. Like trees. + What we want to do now, is to define a recursive function. + A function, that calls itself. +

+

+ This is useful, because it is often shorter and more easily to understand than the iterative version. + In some cases you only can use recursion. +

+

+ This is also a good time to talk about the stack. The stack is the place, were all your local data lives. + You can imagine it as just a big pile of documents. + You can only put stuff on the top or grab something from the top. + This is called push and pop in computer science. +

+

+ So all your local variables and function arguments get pushed on the stack. + When a function ends, the whole block, which belonged to the function (the so called stack frame), + gets popped. The only problem is, that the stack has a limited size. So if you have a a recursive function, + that just keeps calling itself, you will run out of memory on the stack. This is called a stack overflow. + Fortunately memory is cheap these days. So it is not that big of a problem anymore. +

+

+ Your task is to write a recursive function, which returns the nth number of the Fibonacci sequence. + The Fibonacci numbers are a sequence of numbers where each is the sum of both it's predecessors.

+

When:
fib(0) = 0 and fib(1) = 1
Then:
fib(2) = 1
fib(3) = 2

+

We get the following sequence: 0, 1, 1, 2, 3, 5...

diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/meta b/oer/courses/c-basics/sections/03-functions/08-recursion/meta new file mode 100644 index 0000000..046f2c1 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/meta @@ -0,0 +1 @@ +{"title": "Recursion"} diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/program.c b/oer/courses/c-basics/sections/03-functions/08-recursion/program.c new file mode 100644 index 0000000..d7806cb --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/program.c @@ -0,0 +1,8 @@ +#include +// Write a function to return the n-th Fibonacci number +// Use recursive calls to simplify the code + +int main(int argc, const char *argv[]) +{ + printf("the fifth fibonacci number is: %d", fib(5)); +} diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/regex b/oer/courses/c-basics/sections/03-functions/08-recursion/regex new file mode 100644 index 0000000..03cee9a --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/regex @@ -0,0 +1 @@ +^(\s|.)*(3|5)\s*$ diff --git a/oer/courses/c-basics/sections/03-functions/08-recursion/type b/oer/courses/c-basics/sections/03-functions/08-recursion/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/08-recursion/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/Makefile b/oer/courses/c-basics/sections/03-functions/09-scopes/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/content.html b/oer/courses/c-basics/sections/03-functions/09-scopes/content.html new file mode 100644 index 0000000..42070eb --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/content.html @@ -0,0 +1,14 @@ +

+ A scope defines the area in your code, where certain names are visible. This is useful, because at some point you would run out + of meaning full names. The most simple example of the usefulness of scopes are for-loops. + People like to call the loop-counter i and j or x and y or n and m. If you don't have scopes, you could only use the name i ones in your entire program. +

+

+ There are different scope levels. There is the global scope, which is for all global variables of your program, then there is the scope of the compilation unit. + For all intents and purposes is basically the same. When you start to write bigger programs you may break your codes in different compilation units. But for + now you don't have to worry. Then there is block scope. Each block has its one name-space. So if you declare a function, if-statement, some kind of loop or even + just a block, it will have its own scope. +

+

+ You can declare variables with the same name as one in an higher scope. This will overwrite the name till the end of the scope. This is called shadowing +

diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/meta b/oer/courses/c-basics/sections/03-functions/09-scopes/meta new file mode 100644 index 0000000..161acfb --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/meta @@ -0,0 +1 @@ +{"title": "Scope"} diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/program.c b/oer/courses/c-basics/sections/03-functions/09-scopes/program.c new file mode 100644 index 0000000..04b8721 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/program.c @@ -0,0 +1,21 @@ +#include + +static int foo = 10; // This variable lives in global scope + +int main(int argc, const char *argv[]) +{ + int bar = 55; // This is in the scope of the main function + + for(int i= 0; i < 10;) + i += 1; // i is local to this scope + for(int i = 10; i >= 0;) + i -= 1; // so we can reuse i again + + // you can open a block to introduce a scope + { + int foo = 5; // this will overshadow the global foo + printf("foo: %d\n", foo); + } + printf("foo: %d\n", foo); + +} diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/regex b/oer/courses/c-basics/sections/03-functions/09-scopes/regex new file mode 100644 index 0000000..467853d --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/regex @@ -0,0 +1 @@ +^\s*foo: 5\s*foo: 10\s*$ diff --git a/oer/courses/c-basics/sections/03-functions/09-scopes/type b/oer/courses/c-basics/sections/03-functions/09-scopes/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/09-scopes/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/03-functions/10-static/Makefile b/oer/courses/c-basics/sections/03-functions/10-static/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/03-functions/10-static/content.html b/oer/courses/c-basics/sections/03-functions/10-static/content.html new file mode 100644 index 0000000..efc3b79 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/content.html @@ -0,0 +1,3 @@ +

The static keyword enusres that a variable defined at toplevel is only visilbe in it's current c-file. Whereas normal variables can be accesed from other files using the extern keyword. The same applies for functions that are marked static.

+ +

When used in functions the static keyword just ensures that the value of the variable will be retained across calls of the function.

diff --git a/oer/courses/c-basics/sections/03-functions/10-static/meta b/oer/courses/c-basics/sections/03-functions/10-static/meta new file mode 100644 index 0000000..d0bde8b --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/meta @@ -0,0 +1 @@ +{"title": "Static Keyword"} diff --git a/oer/courses/c-basics/sections/03-functions/10-static/program.c b/oer/courses/c-basics/sections/03-functions/10-static/program.c new file mode 100644 index 0000000..41be55d --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/program.c @@ -0,0 +1,15 @@ +#include +void counter() +{ + static int i = 0; + i++; + printf("I was called %d times.\n", i); +} + +int main(int argc, const char *argv[]) +{ + for (int x = 0; x < 20; x++) + { + counter(); + } +} diff --git a/oer/courses/c-basics/sections/03-functions/10-static/regex b/oer/courses/c-basics/sections/03-functions/10-static/regex new file mode 100644 index 0000000..46b9367 --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/regex @@ -0,0 +1 @@ +^(\s|.)*$ diff --git a/oer/courses/c-basics/sections/03-functions/10-static/type b/oer/courses/c-basics/sections/03-functions/10-static/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/10-static/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/03-functions/section b/oer/courses/c-basics/sections/03-functions/section new file mode 100644 index 0000000..364e51e --- /dev/null +++ b/oer/courses/c-basics/sections/03-functions/section @@ -0,0 +1 @@ +{"title": "Functions", "description": "Reuse your Code"} diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/Makefile b/oer/courses/c-basics/sections/10-pointer/01-introduction/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/content.html b/oer/courses/c-basics/sections/10-pointer/01-introduction/content.html new file mode 100644 index 0000000..1842e19 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/content.html @@ -0,0 +1,10 @@ +

+ Sometimes, when you are programming, you need to know, where your data is in memory. This is what pointers are used for. + They point to an specific point in memory, an address. You can then access the data from that pointer via the *-operator. + This is called dereferencing. To get the address of an value, you can use the &-operator. To declare a type as an + pointer to that type just put the *-operator between the type and the name. +

+

+ As a site note: If you want to print out pointer with printf, you have to use the format specifier p. The address will be printed in hexadecimal notation. +

+

For this introduction just familiarize yourself with the basics of pointers. You will be asked to use these concepts yourself in the following exercises.

diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/meta b/oer/courses/c-basics/sections/10-pointer/01-introduction/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/program.c b/oer/courses/c-basics/sections/10-pointer/01-introduction/program.c new file mode 100644 index 0000000..7926b08 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/program.c @@ -0,0 +1,29 @@ +#include +int main(int argc, const char *argv[]) +{ + // Define a pointer + int* p; + // We make p point to another variables value: + int a = 2; + // Initializing the pointer + p = &a; + + // Print value our pointer points to + printf("Value of p: %d\n", *p); + // Print the pointers Memmory adress + printf("Adress of p: %p\n", p); + + + // Access the value of p + *p = 42; + // The value of a is changed + // p points to the memory a is stored in + printf("Value of a: %d\n", a); + printf("Value of p: %d\n", *p); + + a = 27; + // You can also change the value of a + // and the value of p will change + printf("Value of a: %d\n", a); + printf("Value of p: %d\n", *p); +} diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/regex b/oer/courses/c-basics/sections/10-pointer/01-introduction/regex new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/regex @@ -0,0 +1 @@ +.* diff --git a/oer/courses/c-basics/sections/10-pointer/01-introduction/type b/oer/courses/c-basics/sections/10-pointer/01-introduction/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/01-introduction/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/Makefile b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/content.html b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/content.html new file mode 100644 index 0000000..f9a694f --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/content.html @@ -0,0 +1,6 @@ +

+ In the Introduction we already showed you how to dereference a pointer. You just put the *-operator in front of the pointer you want to dereference, to get access to its value. You have to dereference the pointer, when you just want to see the value or when you want to change it. +

+ Now you should try to use pointers for yourself. +

+

Change the following program to print "number: 581" without changing the main function.

diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/meta b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/meta new file mode 100644 index 0000000..b7c5330 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/meta @@ -0,0 +1 @@ +{"title": "Dereferencing"} diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/program.c b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/program.c new file mode 100644 index 0000000..6c4301d --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/program.c @@ -0,0 +1,20 @@ +#include + +void change(int* p) { + // TODO: Change the value of 'number' to 581 here: + + +} + +// Don't change the contents of the main-function for this exercise +int main(int argc, const char *argv[]) +{ + int number = 5; + int* pointer = &number; + + // We call the function 'change' + change(pointer); + + // We print the value of 'number' + printf("value of 'number': %d\n", number); +} diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/regex b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/regex new file mode 100644 index 0000000..846c5c6 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/regex @@ -0,0 +1 @@ +^\s*value of 'number':\ 581\s*$ diff --git a/oer/courses/c-basics/sections/10-pointer/03-dereferencing/type b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/03-dereferencing/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/Makefile b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/Makefile new file mode 100644 index 0000000..a82226f --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/content.html b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/content.html new file mode 100644 index 0000000..4524bf8 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/content.html @@ -0,0 +1,14 @@ +

+ When you are using pointers, you sometimes actually don't want to talk about the address the pointer points to. + Maybe you want to talk about the address next to it. Or you want to get the distance between to pointers in memory. + This is what pointer arithmetic allows you to do. You can use mathematical operations on the addresses of pointers. + All the operations are done relative to the size of the type the pointer refers to. +

+

+ For example, if you have an pointer to a long long, which is 8bytes big, and add one to the pointer, + you will get an address 8bytes from your original pointer. + If you are using an int, you will get one 4bytes from the original. +

+

+ Arrays store all the data next to another in memory. Try using pointer arithmetic to print out all the characters in the array. +

diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/meta b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/meta new file mode 100644 index 0000000..101deb3 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/meta @@ -0,0 +1 @@ +{"title": "Pointer arithmetic"} diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/program.c b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/program.c new file mode 100644 index 0000000..b07ae90 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/program.c @@ -0,0 +1,20 @@ +#include +void print_all(char* word, int len) { + // TODO: print all characters in the array you were given in this function + // don't use the [] operator, do your own calculations on the address +} + +int main(int argc, const char *argv[]) +{ + // We can rely on pointer arithmetic to access values in the array, + // since an arrays values are stored in consecutive memory cells. + char word[] = {'H', 'e', 'l', 'l', 'o'}; + + // Get the arrays second character + // we add the offset 1 to get the second index + char second = *(word + 1); + // We print the arrays second character + printf("%c\n", second); + + print_all(word, 5); +} diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/regex b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/regex new file mode 100644 index 0000000..be570f9 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/regex @@ -0,0 +1 @@ +^(.|\s)*Hello$ diff --git a/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/type b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/04-pointer-arithmetic/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/Makefile b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/Makefile new file mode 100644 index 0000000..a82226f --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/content.html b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/content.html new file mode 100644 index 0000000..4798e5d --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/content.html @@ -0,0 +1,10 @@ +

+ As you may have noticed, you can just as easily use pointer arithmetic to access an array. In fact, that is exactly what the compiler does, + when you use the []-operator. It is just syntactic sugar. But there are some minor differences between pointers and arrays. +

+

+ When you call sizeof on an array it will give you the hole size in bytes of the array. When you call the sizeof on an pointer, + it will just return the size of the pointer, which is on 64bit systems 8bytes. + Also an array always points to the same thing, while a pointer can be changed at any time. + But for the most part they are equivalent. +

diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/meta b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/meta new file mode 100644 index 0000000..054a4f5 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/meta @@ -0,0 +1 @@ +{"title": "Pointers and arrays"} diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/program.c b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/program.c new file mode 100644 index 0000000..4305ddb --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/program.c @@ -0,0 +1,22 @@ +#include + +int main(int argc, const char *argv[]) +{ + int array[] = {1,2,3,4,5,42}; + int array2[] = {4,3,2,1}; + int *pointer = array; + + // The access of an array and a pointer are equivalent + printf("*array = %d, *pointer= %d, array[0] = %d pointer[0] = %d\n", + *array, *pointer, array[0], pointer[0]); + + // you can't do this: + // array = array2; + + // you can do this: + pointer = array2; + + // There are some minor differences between pointers an arrays. + printf("sizeof(array) = %d, sizeof(pointer)= %d", + sizeof(array),sizeof(pointer)); +} diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/regex b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/regex new file mode 100644 index 0000000..c2e835a --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/regex @@ -0,0 +1 @@ +^(.|\s)*$ diff --git a/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/type b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/05-pointer-array-equivalence/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/Makefile b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/content.html b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/content.html new file mode 100644 index 0000000..d9191bf --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/content.html @@ -0,0 +1,10 @@ +

+ An interesting thing you can do with pointers, is the possibility to have pointers point to pointers. + This may seems weird, but it is actually useful. When you want to talk about an array of pointers, + or and array of arrays. +

+

+ To declare a pointer to a pointer you just add more *-operators. + For example char **PointerToPointer; + Nesting pointers like this can easily get confusing, try to avoid using more than two or three. +

diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/meta b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/meta new file mode 100644 index 0000000..c1f7093 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/meta @@ -0,0 +1 @@ +{"title": "Pointers to pointers"} diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/program.c b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/program.c new file mode 100644 index 0000000..9b0db5c --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/program.c @@ -0,0 +1,13 @@ +#include + +int main(int argc, const char *argv[]) +{ + // So why are nested pointers usefull? + // We have seen that arrays and pointers behave simmilarly + // nested arrays can be accessed via nested pointers. + char a = 'a'; + char* b = &a; + char** c = &b; + + // TODO: Print the value of a using c: +} diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/regex b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/regex new file mode 100644 index 0000000..412996f --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/regex @@ -0,0 +1 @@ +^a\s*$ diff --git a/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/type b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/06-pointers-to-pointer/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/Makefile b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/Makefile new file mode 100644 index 0000000..a82226f --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/content.html b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/content.html new file mode 100644 index 0000000..bc73200 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/content.html @@ -0,0 +1,5 @@ +

+ Pointers may also point to functions. This way we can work with functions in a generic way. + To declare a function pointer you still have to use the *-operator. But you also have to write the expected + parameters in parentheses behind the name like this:return-type (*name)(parameters); +

diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/meta b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/meta new file mode 100644 index 0000000..979b461 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/meta @@ -0,0 +1 @@ +{"title": "Function Pointer"} diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/program.c b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/program.c new file mode 100644 index 0000000..8c18530 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/program.c @@ -0,0 +1,32 @@ +#include +void a(int x) +{ + printf("From function a: %d\n", x); +} + +void b(int x) +{ + printf("From function b: %d\n", x); +} + +double c(char y) +{ + printf("From function c: %c\n",y); + return 0.5; +} + +int main(int argc, const char *argv[]) +{ + void (*func)(int); + // The two function calls below look the same but behave diffrent + // we are using a function pointer to change the function being called + // take a good look at the syntax, you are going to need it in the next exercise + func = b; + func(2); + func = a; + func(2); + + // TODO: declare a function pointer for the function c and assigne c to it + + // TODO: call c via function pointer with the argument 'c' +} diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/regex b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/regex new file mode 100644 index 0000000..bd6dcc9 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/regex @@ -0,0 +1 @@ +^\s*From function b: 2\s*From function a: 2\s*From function c: c\s*$ diff --git a/oer/courses/c-basics/sections/10-pointer/07-function-pointer/type b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/07-function-pointer/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/Makefile b/oer/courses/c-basics/sections/10-pointer/08-map/Makefile new file mode 100644 index 0000000..16815b5 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 --std=c99 program.c -o program + gcc --std=c99 --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/content.html b/oer/courses/c-basics/sections/10-pointer/08-map/content.html new file mode 100644 index 0000000..109d3a1 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/content.html @@ -0,0 +1,5 @@ +

+ Now that you know all the basic of pointers, it's time for you to use them in a more in depth way. + Implement a map-function that applies one function to a whole array of integers. + Try to also use pointer arithmetic to index into the array instead of the []-operator. +

diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/meta b/oer/courses/c-basics/sections/10-pointer/08-map/meta new file mode 100644 index 0000000..9c1d955 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/meta @@ -0,0 +1 @@ +{"title": "Map"} diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/program.c b/oer/courses/c-basics/sections/10-pointer/08-map/program.c new file mode 100644 index 0000000..e1e98e2 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/program.c @@ -0,0 +1,21 @@ +#include +int increment(int x) +{ + return x + 1; +} + +//TODO: implement a function map +// It applys the function to all members of the array. +// The first argument is always a pointer to the first argument in a array +// The second is its length and the third is a function that takes +// an integer and returns one. +// Each element in the array is replaced with the fucntions result + +int main(int argc, const char *argv[]) +{ + int nums[7] = {1, 2, 3, 4, 5, 6, 7}; + map(nums, 7, &increment); + for (int i = 0; i < 7; i++) { + printf("%d,", nums[i]); + } +} diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/regex b/oer/courses/c-basics/sections/10-pointer/08-map/regex new file mode 100644 index 0000000..64e3a87 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/regex @@ -0,0 +1 @@ +^2.*8,$ diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/solution.c b/oer/courses/c-basics/sections/10-pointer/08-map/solution.c new file mode 100644 index 0000000..f7de98a --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/solution.c @@ -0,0 +1,19 @@ +#include +int increment(int x) +{ + return x + 1; +} + +int map(int* arr, int len, int (*func)(int)) +{ + for (int i = 0; i < len; i++) + arr[i] = func(arr[i]); +} +int main(int argc, const char *argv[]) +{ + int nums[7] = {1, 2, 3, 4, 5, 6, 7}; + map(nums, 7, &increment); + for (int i = 0; i < 7; i++) { + printf("%d\n", nums[i]); + } +} diff --git a/oer/courses/c-basics/sections/10-pointer/08-map/type b/oer/courses/c-basics/sections/10-pointer/08-map/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/08-map/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/10-pointer/section b/oer/courses/c-basics/sections/10-pointer/section new file mode 100644 index 0000000..047ab21 --- /dev/null +++ b/oer/courses/c-basics/sections/10-pointer/section @@ -0,0 +1 @@ +{"title": "Pointers", "description": "The basics of using pointers and possible pitfalls."} diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/Makefile b/oer/courses/c-basics/sections/11-strings/01-introduction/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/content.html b/oer/courses/c-basics/sections/11-strings/01-introduction/content.html new file mode 100644 index 0000000..c4b6788 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/content.html @@ -0,0 +1,6 @@ +

+ In this course we already did use strings quite a bit. Thats because it is hard to produce easy output with out them. + But C doesn't actualy have strings. Instead C uses arrays of characters. Because strings aren't normaly all the same size, C opted to null terminate all the strings. + I.e the last member of the array is 0, so you don't have to know its size. When we come to the struct lecture you can, if you want, define your own strings to + safe the size. But all the standart library function work only with null terminated char arrays. +

diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/execute.sh b/oer/courses/c-basics/sections/11-strings/01-introduction/execute.sh new file mode 100755 index 0000000..0b7cd4f --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/execute.sh @@ -0,0 +1 @@ +gcc -std=c99 -o program.c program diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/meta b/oer/courses/c-basics/sections/11-strings/01-introduction/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/program.c b/oer/courses/c-basics/sections/11-strings/01-introduction/program.c new file mode 100644 index 0000000..3d2f11e --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/program.c @@ -0,0 +1,19 @@ +#include +int main(int argc, const char *argv[]) +{ + // The two initializations below are equivalent + // String literals are converted into 0-terminated char arrays. + char word[] = "Hi"; + char second_word[] = {'H', 'i', '\0'}; + + // Lets see if the last byte is actually a null byte: + printf("%x\n", word[2]); + printf("%x\n", second_word[2]); + + // Standard library functions such as printf relay on the null-termination + char faulty[] = {'H', 'e', 'l', 'l', 'o'}; + // This will segfault + printf("%s\n", faulty); + // TODO: fix the char array definiton to avoid our programm segfaulting. + // Why do we get a segmentation fault? +} diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/regex b/oer/courses/c-basics/sections/11-strings/01-introduction/regex new file mode 100644 index 0000000..15b1e0f --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/regex @@ -0,0 +1 @@ +^(\s|.)*Hello\s*$ diff --git a/oer/courses/c-basics/sections/11-strings/01-introduction/type b/oer/courses/c-basics/sections/11-strings/01-introduction/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/01-introduction/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/Makefile b/oer/courses/c-basics/sections/11-strings/02-lib/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/content.html b/oer/courses/c-basics/sections/11-strings/02-lib/content.html new file mode 100644 index 0000000..3a48b8f --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/content.html @@ -0,0 +1,8 @@ +

+ In C there are some usefull functions ready to use for strings. + If you want to use them you have to include <string.h>. + Implement a function that concatenates all words beginning with "pre". +

+

+ Try using the functions strncmp and strcat. +

diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/meta b/oer/courses/c-basics/sections/11-strings/02-lib/meta new file mode 100644 index 0000000..94412e8 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/meta @@ -0,0 +1 @@ +{"title": "string.h"} diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/program.c b/oer/courses/c-basics/sections/11-strings/02-lib/program.c new file mode 100644 index 0000000..3d207ba --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/program.c @@ -0,0 +1,33 @@ +#include +#include + +// int strncmp(const char *str1, const char *str2, size_t n) +// returns 0 if n fist characters are equal + +// char *strcat(char *dest, const char *src) +// appeds src to dest. Make sure that dest is big enough. Returns pointer to dest. + +char *ConcatPre(char *Buffer, char *WordArray[], int Count) +{ + // TODO: Implement this function such that all words beginning with "pre" + // will be concatenated and returned. + return Buffer; +} + +int main(int argc, const char *argv[]) +{ + char Buffer[32]; + + char *Words[] = + { + "precompiler ", + "postfix ", + "preprocessor ", + "postprocessing ", + "prefix " + }; + + ConcatPre(Buffer, Words, 5); + + printf("The buffer contains:\n%s \nand has length %d", Buffer, (int)strlen(Buffer)); +} diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/regex b/oer/courses/c-basics/sections/11-strings/02-lib/regex new file mode 100644 index 0000000..6f0ce3a --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/regex @@ -0,0 +1 @@ +^(.|\s)*precompiler preprocessor prefix(.|\s)*32(.|\s)*$ diff --git a/oer/courses/c-basics/sections/11-strings/02-lib/type b/oer/courses/c-basics/sections/11-strings/02-lib/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/02-lib/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/Makefile b/oer/courses/c-basics/sections/11-strings/04-counting/Makefile new file mode 100644 index 0000000..a82226f --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/content.html b/oer/courses/c-basics/sections/11-strings/04-counting/content.html new file mode 100644 index 0000000..4666d51 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/content.html @@ -0,0 +1 @@ +

Write a simple function that counts the number of occurances of a char in a string.

diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/meta b/oer/courses/c-basics/sections/11-strings/04-counting/meta new file mode 100644 index 0000000..d06b029 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/meta @@ -0,0 +1 @@ +{"title": "Char Counter"} diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/program.c b/oer/courses/c-basics/sections/11-strings/04-counting/program.c new file mode 100644 index 0000000..83eb426 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/program.c @@ -0,0 +1,10 @@ +#include +// Returns the number of occurences of c in str +// TODO: Implement a count function that works with the call below +int main(int argc, const char *argv[]) +{ + const char text[] = "Goodbye World!"; + int os = count(text, 'o'); + printf("Number of o's: %d", os); + return 0; +} diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/regex b/oer/courses/c-basics/sections/11-strings/04-counting/regex new file mode 100644 index 0000000..3725589 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/regex @@ -0,0 +1 @@ +(\s|.)*3\s*$ diff --git a/oer/courses/c-basics/sections/11-strings/04-counting/type b/oer/courses/c-basics/sections/11-strings/04-counting/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/04-counting/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/Makefile b/oer/courses/c-basics/sections/11-strings/05-commandline/Makefile new file mode 100644 index 0000000..5dbdcd8 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution +clean: + rm -f program + rm -f solution + diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/content.html b/oer/courses/c-basics/sections/11-strings/05-commandline/content.html new file mode 100644 index 0000000..f92dd67 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/content.html @@ -0,0 +1,14 @@ +

+ When you start a program, you can pass it some arguments. + We actually used this in this course sometimes before, to check your solutions. + But we never did show you how to access this arguments. +

+

+ The main function gets passed two parameters. The first one is the number of arguments. + The second one is an array of strings. They are normally named argc and argv, but you can name them differently. + The first argument is always the path to your program. +

+

+ Write a simple program, which checks, if any arguments got passed and + prints them in reverse order. +

diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/execute.sh b/oer/courses/c-basics/sections/11-strings/05-commandline/execute.sh new file mode 100755 index 0000000..2396955 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/execute.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./program This should be in reverse order diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/meta b/oer/courses/c-basics/sections/11-strings/05-commandline/meta new file mode 100644 index 0000000..87158f5 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/meta @@ -0,0 +1 @@ +{"title": "Commandline Arguments"} diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/program.c b/oer/courses/c-basics/sections/11-strings/05-commandline/program.c new file mode 100644 index 0000000..3e0070b --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/program.c @@ -0,0 +1,17 @@ +#include +int main(int argc, const char **argv) +{ + // TODO: Check if any arguments got passed + { + printf("Please pass arguments to this program"); + return(1); + } + + // TODO: Print the arguments in reverse order + for() + { + printf("%s ",); + } + + return 0; +} diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/solution.c b/oer/courses/c-basics/sections/11-strings/05-commandline/solution.c new file mode 100644 index 0000000..b450702 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/solution.c @@ -0,0 +1,16 @@ +#include +int main(int argc, const char **argv) +{ + if(argc <= 1) + { + printf("Please pass arguments to this program"); + return(1); + } + + for(int index = argc-1; index > 0; index--) + { + printf("%s ", argv[index]); + } + + return(0); +} diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/test.sh b/oer/courses/c-basics/sections/11-strings/05-commandline/test.sh new file mode 100755 index 0000000..b188df1 --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +correct=true + +program1_out=$(./program) +solution1_out=$(./solution) + +if [ "$program1_out" == "$solution1_out" ] +then + echo "PASS " $program1_out " equals " $solution1_out +else + echo "FAIL " $program1_out " DOES NOT EQUAL " $solution1_out + correct = false +fi + +program_out=$(./program This should be in reverse order) +solution_out=$(./solution This should be in reverse order) + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct = false +fi + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + + diff --git a/oer/courses/c-basics/sections/11-strings/05-commandline/type b/oer/courses/c-basics/sections/11-strings/05-commandline/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/05-commandline/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/11-strings/section b/oer/courses/c-basics/sections/11-strings/section new file mode 100644 index 0000000..ce5547c --- /dev/null +++ b/oer/courses/c-basics/sections/11-strings/section @@ -0,0 +1 @@ +{"title": "Strings", "description": "Char arrays and how to use them."} diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/Makefile b/oer/courses/c-basics/sections/12-struct_enum/01-enums/Makefile new file mode 100644 index 0000000..becf11b --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/content.html b/oer/courses/c-basics/sections/12-struct_enum/01-enums/content.html new file mode 100644 index 0000000..b1fce78 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/content.html @@ -0,0 +1,13 @@ +

+ Until now you didn't have any way to define your own types or store information about state in a readable way. + The most simple construct to do that are enums. + Enums are enumeration types, meaning they are basicly ints but they allow you to use a name instead of numbers. + The compiler will then translate those names in numbers. +

+

+ This is usefull, because you see at a glance, what you want to say with your code, instead of trying to find out, what a 4 means in this case. + Also if you want to change anything about your enum, you only have to change it in the definition, except you change the names. +

+

+ Write a function, which returns the number of days to the specified one. +

diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/execute.sh b/oer/courses/c-basics/sections/12-struct_enum/01-enums/execute.sh new file mode 100755 index 0000000..0a69f5c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/execute.sh @@ -0,0 +1,7 @@ +#!/bin/bash + + + +./program 1 5 + + diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/meta b/oer/courses/c-basics/sections/12-struct_enum/01-enums/meta new file mode 100644 index 0000000..a14e38d --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/meta @@ -0,0 +1 @@ +{"title": "Enums"} diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/program.c b/oer/courses/c-basics/sections/12-struct_enum/01-enums/program.c new file mode 100644 index 0000000..35827d3 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/program.c @@ -0,0 +1,95 @@ +#include +#include +#include + +enum Day { + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + SUNDAY +}; + +int DayTill(enum Day Current, enum Day Other) +{ + return 0; +} + +// Unfortunatly there is no easy way to print out enums as text, +// because internaly they are just numbers. +char *EnumToString(char *Dest, enum Day WeekDay) +{ + // When we get to memory allocation you could do this without the destination buffer + switch(WeekDay) + { + case MONDAY: + { + strcpy(Dest,"monday"); + }break; + case TUESDAY: + { + strcpy(Dest,"tuesday"); + }break; + case WEDNESDAY: + { + strcpy(Dest,"wednesday"); + }break; + case THURSDAY: + { + strcpy(Dest,"thursday"); + }break; + case FRIDAY: + { + strcpy(Dest,"friday"); + }break; + case SATURDAY: + { + strcpy(Dest,"saturday"); + }break; + case SUNDAY: + { + strcpy(Dest,"sunday"); + }break; + } + return Dest; +} + +int main(int argc, const char *argv[]) +{ + + // We can now assign variables one of our enums options. + enum Day current_day = MONDAY; + + // To shorten the syntax we can also do a typedefinition: + typedef enum Day DayType; + + // Now we just need to write: + DayType x = TUESDAY; + + // Each of the enums options has an associated value so we can do: + if (x > current_day) { + printf("Tuesday is larger %d.\n", x); + } + char Buffer[32],Buffer2[32]; + printf("Today is %s. %d days until next %s", EnumToString(Buffer, atoi(argv[1])), DayTill(atoi(argv[1]), atoi(argv[2])), EnumToString(Buffer2, atoi(argv[2]))); + +} +// If you want the values to be different, you can set them explicitly +enum Months { + JANUARY = 10, + FEBRUARY = 0, + MARCH = 33, + APRIL = 99, + MAY = 6, + JUNE = 42, + JULY = 27, + AUGUST = 3, + SEPTEMBER = 1, + OCTOBER = 4, + NOVEMBER, + DECEMBER = 5, +}; + + diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/solution.c b/oer/courses/c-basics/sections/12-struct_enum/01-enums/solution.c new file mode 100644 index 0000000..f5e813e --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/solution.c @@ -0,0 +1,74 @@ +#include +#include +#include + +typedef enum Day { + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + SUNDAY +}Day; + +int DayTill(Day Current, Day Other) +{ + if(Current < Other) + { + return Other-Current; + } + else + { + return SUNDAY-Current + Other; + } +} + +char *EnumToString(char *Dest, enum Day WeekDay) +{ + switch(WeekDay) + { + case MONDAY: + { + strcpy(Dest,"monday"); + }break; + case TUESDAY: + { + strcpy(Dest,"tuesday"); + }break; + case WEDNESDAY: + { + strcpy(Dest,"wednesday"); + }break; + case THURSDAY: + { + strcpy(Dest,"thursday"); + }break; + case FRIDAY: + { + strcpy(Dest,"friday"); + }break; + case SATURDAY: + { + strcpy(Dest,"saturday"); + }break; + case SUNDAY: + { + strcpy(Dest,"sunday"); + }break; + } + return Dest; +} + +int main(int argc, const char *argv[]) +{ + if (TUESDAY > MONDAY) { + printf("Tuesday is larger %d.\n", TUESDAY); + } + char Buffer[32],Buffer2[32]; + printf("Today is %s. %d days until next %s", EnumToString(Buffer, atoi(argv[1])), DayTill(atoi(argv[1]), atoi(argv[2])), EnumToString(Buffer2, atoi(argv[2]))); + +} + + + diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/test.sh b/oer/courses/c-basics/sections/12-struct_enum/01-enums/test.sh new file mode 100755 index 0000000..dd95b4a --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/test.sh @@ -0,0 +1,28 @@ +#!/bin/bash + + +correct=true + +for (( i = 0; i < 3; i++ )); do + a=$((RANDOM % 6)) + b=$((RANDOM % 6)) + + program_out=$(./program $a $b) + solution_out=$(./solution $a $b) + + if [ "$program_out" == "$solution_out" ] + then + echo "PASS " $program_out " equals " $solution_out + else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false + fi +done + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/c-basics/sections/12-struct_enum/01-enums/type b/oer/courses/c-basics/sections/12-struct_enum/01-enums/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/01-enums/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/Makefile b/oer/courses/c-basics/sections/12-struct_enum/02-structs/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/content.html b/oer/courses/c-basics/sections/12-struct_enum/02-structs/content.html new file mode 100644 index 0000000..f6349f5 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/content.html @@ -0,0 +1,13 @@ +

+ Structs are another way to define datatypes. They allow you to arange other datatypes into a specific data layout + to form your new data type. Imagine you want to write a program, which does some calculations with vectors. + Instead of using 3 variables for each vector, or a 3 dimentional array, you could have a single datatype for a vector. +

+

+ You then could pass this single vector-type to functions and if you want to access certain members, you can give them convinient names. + To access the x component of the vector, you use the .-operator like this: vector.x. + A struct is declared just like a enum. But, instead of names, you declare members with types. +

+

+ Your task is to define a struct position, which holds the 2d coordinates of the circle and then finish the PrintPos function. +

diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/execute.sh b/oer/courses/c-basics/sections/12-struct_enum/02-structs/execute.sh new file mode 100755 index 0000000..185c136 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/execute.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./program diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/meta b/oer/courses/c-basics/sections/12-struct_enum/02-structs/meta new file mode 100644 index 0000000..7511d47 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/meta @@ -0,0 +1 @@ +{"title": "Structs"} diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/program.c b/oer/courses/c-basics/sections/12-struct_enum/02-structs/program.c new file mode 100644 index 0000000..9e7453f --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/program.c @@ -0,0 +1,32 @@ +#include + +// TODO: Implement the position struct +typedef struct position +{ +}position; + +struct circle { + position pos; + float diameter; +}; + +// As with enums you can use typedef to avoid writing struct everywhere +typedef struct circle Circle; + +// TODO: Finish this function +void PrintPos(Circle cir) +{ + printf("The circle is at position (%4.2f,%4.2f).\n", 0,0); +} + +int main(int argc, const char *argv[]) +{ + // TODO: Set the position to x = 4.5 and y = 2.0 + position CirclePos; + Circle my_circle; + my_circle.pos = CirclePos; + my_circle.diameter = 2; + + PrintPos(my_circle); + return 0; +} diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/regex b/oer/courses/c-basics/sections/12-struct_enum/02-structs/regex new file mode 100644 index 0000000..267a598 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/regex @@ -0,0 +1 @@ +^(.|\s)*(4.50,2.00)(.|\s)*$ diff --git a/oer/courses/c-basics/sections/12-struct_enum/02-structs/type b/oer/courses/c-basics/sections/12-struct_enum/02-structs/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/02-structs/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/Makefile b/oer/courses/c-basics/sections/12-struct_enum/03-flags/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/content.html b/oer/courses/c-basics/sections/12-struct_enum/03-flags/content.html new file mode 100644 index 0000000..7ec1cf2 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/content.html @@ -0,0 +1,15 @@ +

+ Sometimes you need to store lots of diffrent state about a type. + Usualy that it has something or not. It would be wastefull to + use for each feature a single value. The more effitient way is + to store it using flags. +

+

+ To do that, you can use enums. You just have to assigne the values, such that + only one bit is ever set and no member shares a bit. + You can then set multiple flags by or-ing them together using |-operator. + To check, if a flag is set, use the &-operator. +

+

+ Implement a Set and isSet function to make these operations more readable. +

diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/meta b/oer/courses/c-basics/sections/12-struct_enum/03-flags/meta new file mode 100644 index 0000000..6ba8a60 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/meta @@ -0,0 +1 @@ +{"title": "Flags"} diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/program.c b/oer/courses/c-basics/sections/12-struct_enum/03-flags/program.c new file mode 100644 index 0000000..7edd6f0 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/program.c @@ -0,0 +1,56 @@ +#include + +typedef enum Flags +{ + FLAG_NONE = 0, + FLAG_HUNGRY = 1 << 1, + FLAG_THIRSTY = 1 << 2, + FLAG_SLEEPY = 1 << 3, + // TODO: add another flag +}Flags; +/* + * Instead of shifting you can also just write the value + * enum Flags + * { + * foo = 1, + * bar = 2, + * baz = 4, + * } + */ + +void Set(Flags *flag, Flags value) +{ + // TODO: Implement this. +} + +int isSet(Flags flag, Flags value) +{ + // TODO: Implement this + return 0; +} + +typedef enum +{ + GENDER_MALE, + GENDER_FEMALE, +}gender; + +typedef struct person +{ + char *Name; + int Age; + gender Gender; + Flags Condition; +}person; + +int main(int argc, const char *argv[]) +{ + person Charly = {"Charly", 10, GENDER_MALE, FLAG_NONE}; + + Set(&Charly.Condition, FLAG_HUNGRY|FLAG_SLEEPY); + + if(isSet(Charly.Condition, FLAG_SLEEPY)) + { + printf("Charly is sleepy."); + } +} diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/regex b/oer/courses/c-basics/sections/12-struct_enum/03-flags/regex new file mode 100644 index 0000000..daa02c9 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/regex @@ -0,0 +1 @@ +^Charly is sleepy.$ diff --git a/oer/courses/c-basics/sections/12-struct_enum/03-flags/type b/oer/courses/c-basics/sections/12-struct_enum/03-flags/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/03-flags/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/Makefile b/oer/courses/c-basics/sections/12-struct_enum/04-circle/Makefile new file mode 100644 index 0000000..a928c2e --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/Makefile @@ -0,0 +1,11 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution +test: + ./test.sh +execute: + ./execute.sh +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/content.html b/oer/courses/c-basics/sections/12-struct_enum/04-circle/content.html new file mode 100644 index 0000000..6843f46 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/content.html @@ -0,0 +1,3 @@ +

Use the same structs as last time. Write a function, which given a pointer to a circle and a position, can say whether or not the point is within the cirlce.

+ +

Write your own enum to represent the functions result. The Point is inside the circle, when difference of the x-coordinates squared + the difference of the y coordinates squared is less than the radius squared.

diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/execute.sh b/oer/courses/c-basics/sections/12-struct_enum/04-circle/execute.sh new file mode 100755 index 0000000..2daecdb --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/execute.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +for (( i = 0; i < 1; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % 9 ) + 1)) + + ./program $a $b +done diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/meta b/oer/courses/c-basics/sections/12-struct_enum/04-circle/meta new file mode 100644 index 0000000..a3ad691 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/meta @@ -0,0 +1 @@ +{"title": "Circles"} diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/program.c b/oer/courses/c-basics/sections/12-struct_enum/04-circle/program.c new file mode 100644 index 0000000..fbaa675 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/program.c @@ -0,0 +1,52 @@ +#include +#include + +#define Square(x) ((x)*(x)) + +// TODO: Define your result enum +typedef enum result_enum +{ + RESULT_NONE, +}result_enum; + +typedef struct position +{ + float x; + float y; +}position; +typedef struct circle +{ + position pos; + int radius; +}circle; + +result_enum inside(circle c, position p) +{ + // TODO: Implement this function + return RESULT_NONE; +} +int main(int argc, const char *argv[]) +{ + if(argc != 3) + { + printf("Wrong number of Arguments!"); + return 1; + } + float x = atoi(argv[1]); + float y = atoi(argv[2]); + + postion TestPoint = {x,y}; + + psotion CircleCenter = {5,3}; + circle Circle = {CircleCenter, 6}; + + if(inside(Circle, TestPoint)==RESULT_NONE) // TODO: Check for your result enum + { + printf("Point (%f, %f) is Inside the Circle.\n", x,y); + } + else + { + printf("Point (%f, %f) is not Inside the Circle.\n",x,y); + } + return 0; +} diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/solution.c b/oer/courses/c-basics/sections/12-struct_enum/04-circle/solution.c new file mode 100644 index 0000000..4b02fc3 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/solution.c @@ -0,0 +1,62 @@ +#include +#include +#define Square(x) ((x)*(x)) + +typedef struct Point +{ + float x; + float y; +}Point; + +typedef struct Circle +{ + Point Center; + int Radius; +}Circle; + +typedef enum result_enum + { + isInside, + isOutside, + }result_enum; + +result_enum inside(Circle* c, Point* p) +{ + result_enum result; + if(Square(c->Center.x - p->x) + Square(c->Center.y - p->y) <= Square(c->Radius)) + { + result =isInside; + } + else{ + result =isOutside; + } + + return result; +} +int main(int argc, const char *argv[]) +{ + if(argc != 3) + { + printf("Wrong number of Arguments!"); + return 1; + } + float x = atoi(argv[1]); + float y = atoi(argv[2]); + + Point CircleCenter = {5,3}; + Circle C = {CircleCenter, 6}; + + Point p; + p.x = x; + p.y = y; + + if(inside(&C,&p)==isInside) + { + printf("Point (%4.2f, %4.2f) is Inside the Circle.\n", x, y); + } + else + { + printf("Point (%4.2f, %4.2f) is not Inside the Circle.\n", x, y); + } + return 0; +} diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/test.sh b/oer/courses/c-basics/sections/12-struct_enum/04-circle/test.sh new file mode 100755 index 0000000..3c2ce0a --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/test.sh @@ -0,0 +1,29 @@ +#!/bin/bash + + +correct=true + +for (( i = 0; i < 3; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % 9 ) + 1)) + + program_out=$(./program $a $b) + solution_out=$(./solution $a $b) + + if [ "$program_out" == "$solution_out" ] + then + echo "PASS " $program_out " equals " $solution_out + else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false + fi +done + + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi diff --git a/oer/courses/c-basics/sections/12-struct_enum/04-circle/type b/oer/courses/c-basics/sections/12-struct_enum/04-circle/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/04-circle/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/Makefile b/oer/courses/c-basics/sections/12-struct_enum/05-unions/Makefile new file mode 100644 index 0000000..c531e6c --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/content.html b/oer/courses/c-basics/sections/12-struct_enum/05-unions/content.html new file mode 100644 index 0000000..5c6947f --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/content.html @@ -0,0 +1,17 @@ +

+ The last construct to lay out your data are unions. Unions are used to store different types in the same memory location. + This has three main practical reasons: +

    +
  1. Naming the same data differently.
    + Lets say you want a 3d vector, which you can use both as position and as color. You can use a union to define it as x,y,z and r,g,b.
  2. +
  3. Storing different data in the same location.
    + To do that, you use the union to declare which types you want to store and and enum to store, which type actually got stored.
  4. +
  5. Accessing the same data in a different way.
    + If you are doing low level programming, you sometimes have to deal with the byte order of different platforms. + It could then be useful to access types in form of bytes. +
  6. +
+

+

+ Your task is to define the struct box, which holds either an int or an float in the same position and tells you with an enum what it has stored. +

diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/meta b/oer/courses/c-basics/sections/12-struct_enum/05-unions/meta new file mode 100644 index 0000000..60b2cdd --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/meta @@ -0,0 +1 @@ +{"title": "Unions"} diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/program.c b/oer/courses/c-basics/sections/12-struct_enum/05-unions/program.c new file mode 100644 index 0000000..9627b97 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/program.c @@ -0,0 +1,58 @@ +#include + +typedef union vec3 +{ + struct{float x,y,z;}; + struct{float r,g,b;}; + float E[3]; +}vec3; + +typedef enum type +{ + TYPE_INT, + TYPE_FLOAT, +}type; + +// TODO: fill in the struct +typedef struct box +{ + +}box; + +// TODO: implement this function, such that it prints the numbers in the right format. +// this function should just print the number and a newline (\n) +void PrintBox(box Box) +{ + // You can use a switch here. +} + +int main(int argc, int argv) +{ + vec3 Vector = {1.0f,2.0f,3.0f}; + + // You can use r,g and b + printf("Color: %2.2f, %2.2f, %2.2f\n", Vector.r, Vector.g, Vector.b); + + printf("Before the loop:\n"); + // You can use x,y and z + printf("Position: %2.2f, %2.2f, %2.2f\n", Vector.x, Vector.y, Vector.z); + + // You can access the elements via array + for (int i = 0; i < 3; i++) + { + Vector.E[i] = 10.0f; + } + + printf("After the loop:\n"); + printf("Position: %2.2f, %2.2f, %2.2f\n", Vector.x, Vector.y, Vector.z); + + box BoxInt; + box BoxFloat; + + // TODO: fill this variables both with the appropriate type and with 15 as a value + + PrintBox(BoxInt); + PrintBox(BoxFloat); + + return 0; +} diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/regex b/oer/courses/c-basics/sections/12-struct_enum/05-unions/regex new file mode 100644 index 0000000..da81f3e --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/regex @@ -0,0 +1 @@ +^(.|\s)*15\s*15.0*(.|\s)*$ diff --git a/oer/courses/c-basics/sections/12-struct_enum/05-unions/type b/oer/courses/c-basics/sections/12-struct_enum/05-unions/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/05-unions/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/12-struct_enum/section b/oer/courses/c-basics/sections/12-struct_enum/section new file mode 100644 index 0000000..5cf6616 --- /dev/null +++ b/oer/courses/c-basics/sections/12-struct_enum/section @@ -0,0 +1 @@ +{"title": "Structs & Enums", "description": "Datastructures to simplify programs."} diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/Makefile b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/Makefile new file mode 100644 index 0000000..917cde0 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/Makefile @@ -0,0 +1,7 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 -DSOMETHING program.c -o program2 +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/content.html b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/content.html new file mode 100644 index 0000000..2ffee24 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/content.html @@ -0,0 +1,16 @@ +

+ You already learned how to use the preprocessor to include libraries and to use macros. + But there some features you didn't learn yet. One very powerful one is conditional compilation. + This means you can mark up your code with the preprocessor directives #if, #ifdef and #ifndef, + to define, if this code gets to be compiled or will get cut out. + You can give the compiler flags starting with -D to define a flag for the preprocessor to check on. +

+

+ You do this for many reasons. For example you want to make your code platform agnostic. Then you can wrap your system calls with those blocks. Another example could be, if you want to define debug-behavior, which should not end up in the release code. +

+

+As a reminder: The preprocessor runs before the compiler. It only modifies the sourcefile before it is passed to the compiler. It does not change how the compiler behaves. +

+

+ Check if the preprocessor flag SOMETHING is checked. +

diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/execute.sh b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/execute.sh new file mode 100755 index 0000000..faf16c8 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/execute.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo Compiler: gcc -std=c99 program.c -o program +./program +echo +echo Compiler: gcc -std=c99 -DSOMETHING program.c -o program2 +./program2 diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/meta b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/meta new file mode 100644 index 0000000..6242557 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/meta @@ -0,0 +1 @@ +{"title": "Conditional Compilation"} diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/program.c b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/program.c new file mode 100644 index 0000000..480ab05 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/program.c @@ -0,0 +1,10 @@ +#include + +int main(int argc, const char *argv[]) +{ + // print this, if the compiler defined -DSOMETHING + printf("something was defined\n"); + + // print this if the compiler did not define -DSOMETHING + printf("something was not defined\n"); +} diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/test.sh b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/test.sh new file mode 100755 index 0000000..3d3f4b9 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/test.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +program1_out=$(./program) +program2_out=$(./program2) + +pass=true + +if [ "$program1_out" == "something was not defined" ] +then + test1="PASS Test1" +else + test1="FAIL Test1" + pass=false +fi + +if [ "$program2_out" == "something was defined" ] +then + test2="PASS Test2" +else + test2="FAIL Test2" + pass=false +fi + +if [ "$pass" == true ] +then + echo PASS +else + echo FAIL +fi +echo " " $test1 +echo " " $test2 + + diff --git a/oer/courses/c-basics/sections/17-preprocessor/01-introduction/type b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/type new file mode 100644 index 0000000..0f28ac9 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/01-introduction/type @@ -0,0 +1,2 @@ +program/scriptgrade + diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/Makefile b/oer/courses/c-basics/sections/17-preprocessor/02-debug/Makefile new file mode 100644 index 0000000..e3cf10a --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/Makefile @@ -0,0 +1,12 @@ + +all: + gcc --std=c99 -DDEBUG -Ddebug -DDebug program.c -o debug_program + gcc --std=c99 program.c -o program + gcc --std=c99 -DDEBUG -Ddebug -DDebug solution.c -o debug_solution + gcc --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution + rm -f debug_program + rm -f debug_solution diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/content.html b/oer/courses/c-basics/sections/17-preprocessor/02-debug/content.html new file mode 100644 index 0000000..291cd1e --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/content.html @@ -0,0 +1,12 @@ +

+ When programming, you will definitely run into situations, where you code something with the only purpose to help you debug. + You probably don't want those functions in the released program. A simple way to do this, is to wrap them in a macro, which gets defined + to nothing, if you didn't set the compiler flag for debug-mode (e.g -DDEBUG). +

+

+ Another feature from the preproccessor you can use for debugging is the compile time information. With __FILE__ you get the filename and with __LINE__ the line number. + With that you can augment your debugging prints to include information about the file and line. +

+

+ Define the debug() macro, that behaves like printf but only actually prints when the variable '-DDEBUG' is set. +

diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/execute.sh b/oer/courses/c-basics/sections/17-preprocessor/02-debug/execute.sh new file mode 100755 index 0000000..c32ed3b --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/execute.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +echo Debugmode on: +./debug_program +echo Debugmode off: +./program diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/meta b/oer/courses/c-basics/sections/17-preprocessor/02-debug/meta new file mode 100644 index 0000000..1db56ab --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/meta @@ -0,0 +1 @@ +{"title": "A Debug Helper"} diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/program.c b/oer/courses/c-basics/sections/17-preprocessor/02-debug/program.c new file mode 100644 index 0000000..75fbdcb --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/program.c @@ -0,0 +1,30 @@ +#include +#include + +// TODO: Change the debug macro to behave like printf when -DDebug is set +// And to do nothing if not; +#define debug(String, ...) +// The three dots mean, you can pass as many or as little arguments as you want +// to access these arguments use __VA_ARGS__ + +// a macro for simple error output with some extra debug info +#define ERROR(Text) printf("ERROR: File: %s Function: %s Line: %d. %s\n", __FILE__, __func__, __LINE__, Text) +// TODO: wrap this macro as well + +int main(int argc, const char *argv[]) +{ + // Sometimes you just want to print stuff when debugging + // and it is tedious to constantly remove them just to add then later again + int foo = 42; + debug("%d\n", foo); + + // Maybe you want to use the preprocessor to log errors. + // It could be useful to print out some information like the + // line number, filename and function name + + if(foo != 30) + { + // Logging the Error + ERROR("Something went wrong!"); + } +} diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/solution.c b/oer/courses/c-basics/sections/17-preprocessor/02-debug/solution.c new file mode 100644 index 0000000..9e6807d --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/solution.c @@ -0,0 +1,28 @@ +#include +#include + +#ifdef DEBUG + +#define debug(String, ...) printf(String, __VA_ARGS__) +#define ERROR(Text) printf("ERROR: File: %s Function: %s Line: %d. %s\n", __FILE__, __func__, __LINE__, Text) + +#else + +#define debug(String, ...) +#define ERROR(Text) + +#endif + +int main(int argc, const char *argv[]) +{ + int foo = 42; + debug("%d\n", foo); + + if(foo != 30) + { + // Logging the Error + ERROR("Something went wrong!"); + } + + +} diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/test.sh b/oer/courses/c-basics/sections/17-preprocessor/02-debug/test.sh new file mode 100755 index 0000000..07ccc71 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +correct=true + +program_out=$(./debug_program) +solution_out=$(./debug_solution) + +regex='^\s*42\s*ERROR: File:(.|\s)*$' +if [[ $program_out =~ $regex ]] +then + echo "Pass " +else + echo "FAIL " $program_out + correct = false +fi + +program_out=$(./program) +solution_out=$(./solution) + +regex2='^\s*' +if [[ $program_out =~ $regex2 ]] +then + echo "PASS " +else + echo "FAIL " $program_out + correct=false +fi + +if [ "$correct"==true] +then + echo "PASS"; +else + echo "FAIL"; +fi diff --git a/oer/courses/c-basics/sections/17-preprocessor/02-debug/type b/oer/courses/c-basics/sections/17-preprocessor/02-debug/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/02-debug/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/Makefile b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/Makefile new file mode 100644 index 0000000..10304ff --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 program.c -o program -lm + + +clean: + rm -f program + diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/content.html b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/content.html new file mode 100644 index 0000000..02c35dc --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/content.html @@ -0,0 +1 @@ +

You may have noticed in previous courses, that in the beginning of the file we often write somthing like #include. This tells the preprocessor to include the standart io library to your program.

diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/meta b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/meta new file mode 100644 index 0000000..6fb0443 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/meta @@ -0,0 +1 @@ +{"title": "Include"} diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/program.c b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/program.c new file mode 100644 index 0000000..cc6f4d7 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/program.c @@ -0,0 +1,25 @@ +#include +#include +// You typicly write all of your includes in the beginning + +// We want to use some math function. +// To do so we have to either write them our self or include a library. +// Because we are lazy and don't want to spend time debugging we will include the math.h library. + +// TODO: Include math.h +// Be carefull! For some libraries you have to tell the linker which libraries he has to link to your program +// I.g in this case, because we are compiling with gcc, we need to set the -lm flag + +int main(int argc, const char *argv[]) +{ + int Value = 90; + float SinValue = sin(Value); + float CosinValue = cos(Value); + printf("The sin of %d is %4.2f and the cosin is %4.2f.", Value, SinValue, CosinValue); +} + +// On many linux-distributions you can use "man " to get information +// If you are on linux, try using : +// man atof +// man printf +// man sin diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/regex b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/regex new file mode 100644 index 0000000..7e6f8ca --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/regex @@ -0,0 +1 @@ +^The sin of 90 is 0.89 and the cosin is -0.45.$ diff --git a/oer/courses/c-basics/sections/17-preprocessor/03-libraries/type b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/03-libraries/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/17-preprocessor/section b/oer/courses/c-basics/sections/17-preprocessor/section new file mode 100644 index 0000000..acceea5 --- /dev/null +++ b/oer/courses/c-basics/sections/17-preprocessor/section @@ -0,0 +1 @@ +{"title": "Preprocessor", "description": "Preprocessing on your source code."} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/content.html b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/content.html new file mode 100644 index 0000000..f905c78 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/content.html @@ -0,0 +1,20 @@ +

+ You already learned a bit about the stack. Now it is time to take deeper look at how the stack works and what it is used for. +

+

+ The stack handles basically anything concerning your subroutines. It provides a simple way to change to a different function and return while keeping all the local data accessible. +

+

+ Earlier we told you, that the stack only can pop and push. This is normally true, but to achieve the calling and returning of the function, we need two more instructions. The call instruction and the ret instruction. This is all done with only two pointers into your stack memory. +

+

+ We need to know the top of the stack. This is handled with the stack pointer. And we need to know the position of the old stack pointer, the one before we called a subroutine. That is the base pointer. Together they form the current stack frame. +

+

+So how does calling a function work? This can vary from architecture to architecture, but there are lots of similarities. You first have to save certain registers. There are conventions for each register, if the caller or the callee has to save them. Then all the arguments for the subroutine get pushed followed by the return address. Finally the old base pointer gets pushed on the stack and the new one points to the stack pointer. Now the stack is prepared for the subroutine. +

+

+ The stack is then used to hold all your local data or to call more functions. To return you simply move the stack pointer to the base pointer and then pop the old base pointer. Then you call ret, which + just changes the instruction pointer to the return address. Last but not least you have to restore the registers. If the function has a return value, you have to place it in the designated return register. On x86 platforms it is + the eax register. +

diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/meta b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/meta new file mode 100644 index 0000000..2892de8 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/meta @@ -0,0 +1 @@ +{"title": "Stack Revision"} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/type b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/01-introduction/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/Makefile b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/Makefile new file mode 100644 index 0000000..b5d8321 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/Makefile @@ -0,0 +1,6 @@ + +all: + gcc --std=c99 fib.c program.c -o program + +clean: + rm -f program \ No newline at end of file diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/content.html b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/content.html new file mode 100644 index 0000000..04ae7d0 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/content.html @@ -0,0 +1,20 @@ +

+ Up until now all our data has been allocated on the stack. + This is fine for most purposes, but limits our ability to hold memory globally, instead of local to a function. + When a function returns, all of its local data gets popped of the stack and can't be used later. + Also the stack is smaller than the heap. So even if you only need a giant block of memory in a function, you should allocate it on the heap. +

+

+ To allocate memory on the heap, you use functions like malloc. You have to specify the size in bytes you want to allocate. + Because the heap doesn't know, when you don't need your data anymore, you have to free it yourself. Otherwise this memory can't be used + by other processes. This is commonly called a memory leak. To free the memory you call functions like free. You have to pass the pointer to + the memory you want to free. +

+

+ Unfortunately the heap is slower than the stack. So if you see yourself allocating lots of stuff in a row, maybe think about allocating it in one go and + use pointer-arithmetic to get pointers with the right offsets. +

+

+ In the following code we have a function that builds an array with all numbers of the Fibonacci sequence up until the n-ths one using the fib-function from earlier in + the course. But when you run it you will notice that something is wrong. Try to fix it. +

diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.c b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.c new file mode 100644 index 0000000..391e926 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.c @@ -0,0 +1,9 @@ +#include "fib.h" +int fib(int n) +{ + if (n == 0) + return 0; + if (n == 1) + return 1; + return (fib(n - 1) + fib(n - 2)); +} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.h b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.h new file mode 100644 index 0000000..5a3331e --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/fib.h @@ -0,0 +1,6 @@ +#ifndef FIB_H +#define FIB_H + +int fib(int n); + +#endif diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/meta b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/meta new file mode 100644 index 0000000..566eaf3 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/meta @@ -0,0 +1 @@ +{"title": "The Heap"} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/program.c b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/program.c new file mode 100644 index 0000000..ecc2f2d --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/program.c @@ -0,0 +1,31 @@ +#include +#include +#include "fib.h" + +// TODO: Fix this function. +int* BuildFibArray(int n) +{ + int Numbers[n]; + for (int x = 0; x < n; x++) { + Numbers[x] = fib(x); + } + int *Array = Numbers; + return Array; +} + +int main(int argc, const char *argv[]) +{ + int *fibs = BuildFibArray(10); + + // Doing some stuff that could overide the values we point to + fib(5); + + printf("Fib: "); + for (int i = 0; i < 10; i++) + printf("%d, ", fibs[i]); + printf("\n"); + + // As you noticed this doesn't print out the right numbers + // That is because, when we return from the function, the array is no longer allocated. + // So the pointer points to just garbage. If we are lucky nothing did overwrite the values, but normaly thats not the case. +} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/regex b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/regex new file mode 100644 index 0000000..8c09097 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/regex @@ -0,0 +1 @@ +^\s*Fib: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34,\s*$ \ No newline at end of file diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/type b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/02-heap/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/Makefile b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/Makefile new file mode 100644 index 0000000..becf11b --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/content.html b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/content.html new file mode 100644 index 0000000..f6b5fd1 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/content.html @@ -0,0 +1,8 @@ +

+ Another example were you could allocate memory on the heap is the concatenation of two strings. + This has the advantage that you don't have to pass memory with the right size into the function. + The downside is, that you have to remember to free the memory when you don't need it anymore. +

+

+ Implement the concat function with malloc. +

diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/execute.sh b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/execute.sh new file mode 100755 index 0000000..0aaad72 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/execute.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +program_out=$(./program) +echo $program_out diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/meta b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/meta new file mode 100644 index 0000000..7b59830 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/meta @@ -0,0 +1 @@ +{"title": "Example"} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/program.c b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/program.c new file mode 100644 index 0000000..586fdd2 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/program.c @@ -0,0 +1,16 @@ +#include +// TODO: Include the approriate headers +char* concat(char* first, char* second) +{ + // TODO: allocate memory and copy both strings to it +} +int main(int argc, const char *argv[]) +{ + char hello[] = "Hello"; + char world[] = "World!"; + + char* out = concat(hello, world); + printf("%s", out); + + // Don't forget to free the memory +} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/solution.c b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/solution.c new file mode 100644 index 0000000..4a77450 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/solution.c @@ -0,0 +1,27 @@ +#include +// TODO: Include the approriate headers +#include +char* concat(char* first, char* second) +{ + // TODO: allocate dynamic memory and copy both strings to it + char* both = malloc(sizeof(char) * 13); + int x = 0; + while (first[x] != 0) { + both[x] = first[x]; + x++; + } + int y = 0; + while (second[y] != 0) { + both[x + y] = second[y]; + y++; + } + return both; +} +int main(int argc, const char *argv[]) +{ + char hello[] = "Hello"; + char world[] = "World!"; + + char* out = concat(hello, world); + printf("%s", out); +} diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/test.sh b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/test.sh new file mode 100755 index 0000000..aae0644 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + + +correct=true + +program_out=$(./program) +solution_out=$(./solution) + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false +fi + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/type b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/04-concat-strings/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/24-dynamic-memory/section b/oer/courses/c-basics/sections/24-dynamic-memory/section new file mode 100644 index 0000000..a8b6224 --- /dev/null +++ b/oer/courses/c-basics/sections/24-dynamic-memory/section @@ -0,0 +1 @@ +{"title": "Memory", "description": "Stack vs. Heap"} diff --git a/oer/courses/c-basics/sections/26-files/01-read/Lorem_Ipsum.txt b/oer/courses/c-basics/sections/26-files/01-read/Lorem_Ipsum.txt new file mode 100644 index 0000000..102374b --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/Lorem_Ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/oer/courses/c-basics/sections/26-files/01-read/Makefile b/oer/courses/c-basics/sections/26-files/01-read/Makefile new file mode 100644 index 0000000..b3b65da --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/Makefile @@ -0,0 +1,8 @@ + +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/26-files/01-read/content.html b/oer/courses/c-basics/sections/26-files/01-read/content.html new file mode 100644 index 0000000..efb3a37 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/content.html @@ -0,0 +1,2 @@ +

Something you almost always will have to deal with is the reading +or writing of files to or from the hard-drive.

diff --git a/oer/courses/c-basics/sections/26-files/01-read/execute.sh b/oer/courses/c-basics/sections/26-files/01-read/execute.sh new file mode 100755 index 0000000..0aaad72 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/execute.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +program_out=$(./program) +echo $program_out diff --git a/oer/courses/c-basics/sections/26-files/01-read/meta b/oer/courses/c-basics/sections/26-files/01-read/meta new file mode 100644 index 0000000..e9a40bf --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/meta @@ -0,0 +1 @@ +{"title": "Reading Files"} diff --git a/oer/courses/c-basics/sections/26-files/01-read/program.c b/oer/courses/c-basics/sections/26-files/01-read/program.c new file mode 100644 index 0000000..e10f009 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/program.c @@ -0,0 +1,37 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + // First we must open the file. we have to pass the name and our mode. + // we only want to read so we pass "r" + FILE *file = fopen("Lorem_Ipsum.txt","r"); + + // Check if we succeded + if(file) + { + // TODO: Read up on how to get the filesize and the data from the file with stdio + // tipp: fseek, ftell, fread ... + + // TODO: Get the filesize + int Filesize = 0; + + char *Buffer = malloc(sizeof(char)*(Filesize+1)); + Buffer[Filesize] = 0; + // This is optianal but it is sometimes convenient to nullterminate your buffer + // If you dont want to do that you just have to allocate the exact amount + + // TODO: Copy the data into the Buffer + + // Now you have read the data into a buffer and you could mess with it, if you wanted to. + // For now were will just print it out; + printf("%s", Buffer); + + // if you use the file the whole liftime of the program you actualy don't need to close it. + fclose(file); + } + else + { + // Here you could write your error handling or log the error; + } +} diff --git a/oer/courses/c-basics/sections/26-files/01-read/solution.c b/oer/courses/c-basics/sections/26-files/01-read/solution.c new file mode 100644 index 0000000..8a67969 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/solution.c @@ -0,0 +1,30 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + FILE *file = fopen("Lorem_Ipsum.txt","r"); + + if(file) + { + fseek(file, 0 , SEEK_END); + int Filesize = ftell(file); + rewind(file); + + char *Buffer = malloc(sizeof(char)*(Filesize+1)); + Buffer[Filesize] = 0; + + fread(Buffer, 1, Filesize, file); + + // Now you have read the data into a buffer and you could mess with it, if you wanted to. + // For now were will just print it out; + printf("%s", Buffer); + + // if you use the file the whole liftime of the program you actualy don't need to close it. + fclose(file); + } + else + { + // Here you could write your error handling or log the error; + } +} diff --git a/oer/courses/c-basics/sections/26-files/01-read/test.sh b/oer/courses/c-basics/sections/26-files/01-read/test.sh new file mode 100755 index 0000000..aae0644 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + + +correct=true + +program_out=$(./program) +solution_out=$(./solution) + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false +fi + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/c-basics/sections/26-files/01-read/type b/oer/courses/c-basics/sections/26-files/01-read/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/01-read/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/26-files/02-write/Makefile b/oer/courses/c-basics/sections/26-files/02-write/Makefile new file mode 100644 index 0000000..b9a49c2 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/Makefile @@ -0,0 +1,7 @@ +all: + gcc --std=c99 program.c -o program + gcc --std=c99 solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-basics/sections/26-files/02-write/content.html b/oer/courses/c-basics/sections/26-files/02-write/content.html new file mode 100644 index 0000000..b6990fd --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/content.html @@ -0,0 +1,4 @@ +

Sometimes you don't only want your programs to just diplay some +stuff on the screen or some text in a console. You want them to +manipulate data and store it somewhere. This is what we are doing +now.

diff --git a/oer/courses/c-basics/sections/26-files/02-write/execute.sh b/oer/courses/c-basics/sections/26-files/02-write/execute.sh new file mode 100755 index 0000000..ef209cf --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/execute.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +./program This is a Test. +cat output.txt + diff --git a/oer/courses/c-basics/sections/26-files/02-write/meta b/oer/courses/c-basics/sections/26-files/02-write/meta new file mode 100644 index 0000000..55823a0 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/meta @@ -0,0 +1 @@ +{"title": "Writing Files"} diff --git a/oer/courses/c-basics/sections/26-files/02-write/program.c b/oer/courses/c-basics/sections/26-files/02-write/program.c new file mode 100644 index 0000000..054932c --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/program.c @@ -0,0 +1,20 @@ +#include +#include + +// This time we make a simple program, which just writes its arguments into a file +int main(int argc, char *argv[]) +{ + // TODO: read up on all the modes and choose the one, that creates a new file and dicards the old one. + FILE *file = fopen("output.txt", ""); + + if(file) + { + for(int Index = 0; Index < argc; Index++) + { + char *CurrentString = argv[Index]; + // TODO: print the string into the file. Each one in a new line + // TIP: fprintf + } + fclose(file); + } +} diff --git a/oer/courses/c-basics/sections/26-files/02-write/solution.c b/oer/courses/c-basics/sections/26-files/02-write/solution.c new file mode 100644 index 0000000..a98b519 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/solution.c @@ -0,0 +1,18 @@ +#include +#include + +// This time we make a simple program, which just writes its arguments into a file +int main(int argc, char *argv[]) +{ + FILE *file = fopen("output.txt", "w"); + + if(file) + { + for(int Index = 1; Index < argc; Index++) + { + char *CurrentString = argv[Index]; + fprintf(file, "%s ",CurrentString); + } + fclose(file); + } +} diff --git a/oer/courses/c-basics/sections/26-files/02-write/test.sh b/oer/courses/c-basics/sections/26-files/02-write/test.sh new file mode 100755 index 0000000..68af8d6 --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/test.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +correct=true + +./program This is a test +program_out=$(cat output.txt) +./solution This is a test +solution_out=$(cat output.txt) + +if [ "$program_out" == "$solution_out" ] +then + echo "PASS " $program_out " equals " $solution_out +else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false +fi + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/c-basics/sections/26-files/02-write/type b/oer/courses/c-basics/sections/26-files/02-write/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/02-write/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-basics/sections/26-files/section b/oer/courses/c-basics/sections/26-files/section new file mode 100644 index 0000000..215f62a --- /dev/null +++ b/oer/courses/c-basics/sections/26-files/section @@ -0,0 +1 @@ +{"title": "Files", "description": "Learn how to handle files in c."} diff --git a/oer/courses/c-mpi/meta b/oer/courses/c-mpi/meta new file mode 100644 index 0000000..30d5a51 --- /dev/null +++ b/oer/courses/c-mpi/meta @@ -0,0 +1 @@ +{"title": "MPI: Message Passing Interface", "description": "A quick introduction to MPI. A basic understanding of C is a requirment for this course."} diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/Makefile b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/Makefile new file mode 100644 index 0000000..cc4fe35 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/Makefile @@ -0,0 +1,5 @@ + +all: + mpicc -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/content.html b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/content.html new file mode 100644 index 0000000..722e2ba --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/content.html @@ -0,0 +1,5 @@ +

MPI is a parallelization framework for use on multiple machines and processors.

+ +

For this first exercise, we will send a single integer from one process to the other. +

+ diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/job.slurm b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/job.slurm new file mode 100644 index 0000000..07240f1 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/job.slurm @@ -0,0 +1,3 @@ +#!/bin/sh +#SBATCH -N 2 +mpiexec program diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/meta b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/meta new file mode 100644 index 0000000..210a30b --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/meta @@ -0,0 +1 @@ +{"title": "Hello World!"} diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/program.c b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/program.c new file mode 100644 index 0000000..97532e1 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/program.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + int rank; + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + srand(2); + int random = rand(); + MPI_Send(&random, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); + printf("rank 0 random: %d \t", random); + } else if (rank == 1) { + int random; + // Recieve data from rank 0 here: + printf("rank 1, random: %d", random); + } + MPI_Finalize(); +} diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/regex b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/regex new file mode 100644 index 0000000..ed41b84 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/regex @@ -0,0 +1 @@ +rank\s\d\srandom:\s(\d*).*\1$ diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/solution.c b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/solution.c new file mode 100644 index 0000000..d87e78d --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/solution.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + int rank; + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) { + srand(2); + int random = rand(); + MPI_Send(&random, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); + printf("rank 0 random: %d \t", random); + } else if (rank == 1) { + int random; + MPI_Recv(&random, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("rank 1, random: %d", random); + } + MPI_Finalize(); +} diff --git a/oer/courses/c-mpi/sections/01-introduction/01-c-hello/type b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/type new file mode 100644 index 0000000..1960383 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/01-c-hello/type @@ -0,0 +1 @@ +program/match-regex-parallel diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/Makefile b/oer/courses/c-mpi/sections/01-introduction/02-bcast/Makefile new file mode 100644 index 0000000..cc4fe35 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/Makefile @@ -0,0 +1,5 @@ + +all: + mpicc -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/content.html b/oer/courses/c-mpi/sections/01-introduction/02-bcast/content.html new file mode 100644 index 0000000..c9233ca --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/content.html @@ -0,0 +1 @@ +

We have sucessfully sent a single value from one process to another, now we will brodcast the value to all other processes instead.

diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/job.slurm b/oer/courses/c-mpi/sections/01-introduction/02-bcast/job.slurm new file mode 100644 index 0000000..0d617e3 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/job.slurm @@ -0,0 +1,3 @@ +#!/bin/sh +#SBATCH -n 4 +mpiexec program diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/meta b/oer/courses/c-mpi/sections/01-introduction/02-bcast/meta new file mode 100644 index 0000000..210a30b --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/meta @@ -0,0 +1 @@ +{"title": "Hello World!"} diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/program.c b/oer/courses/c-mpi/sections/01-introduction/02-bcast/program.c new file mode 100644 index 0000000..63e1310 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/program.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + int rank; + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + int random; + if (rank == 0) { + srand(2); + random = rand(); + } + // Add the broadcast directive below: + + printf("rank %d, random: %d\n", rank, random); + MPI_Finalize(); +} diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/regex b/oer/courses/c-mpi/sections/01-introduction/02-bcast/regex new file mode 100644 index 0000000..11d91f9 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/regex @@ -0,0 +1 @@ +.*random:\s(\d{2,})\n.*\1\n.*\1.*\n.*\1 diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/solution.c b/oer/courses/c-mpi/sections/01-introduction/02-bcast/solution.c new file mode 100644 index 0000000..26680c2 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/solution.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +int main(int argc, char *argv[]) +{ + int rank; + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + int random; + if (rank == 0) { + srand(2); + random = rand(); + } + MPI_Bcast(&random, 1, MPI_INT, 0, MPI_COMM_WORLD); + printf("rank %d, random: %d\n", rank, random); + MPI_Finalize(); +} diff --git a/oer/courses/c-mpi/sections/01-introduction/02-bcast/type b/oer/courses/c-mpi/sections/01-introduction/02-bcast/type new file mode 100644 index 0000000..1960383 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/02-bcast/type @@ -0,0 +1 @@ +program/match-regex-parallel diff --git a/oer/courses/c-mpi/sections/01-introduction/section b/oer/courses/c-mpi/sections/01-introduction/section new file mode 100644 index 0000000..bab5de8 --- /dev/null +++ b/oer/courses/c-mpi/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Introduction", "description": "The very basics."} diff --git a/oer/courses/c-newcomers/meta b/oer/courses/c-newcomers/meta new file mode 100644 index 0000000..48d7c46 --- /dev/null +++ b/oer/courses/c-newcomers/meta @@ -0,0 +1 @@ +{"title": "C for Newcomers", "description": "An introductory course covering concepts of the programming language C and computer science. It is intended for people, who have little background in computer science."} diff --git a/oer/courses/c-newcomers/sections/01-introduction/00-welcome/content.md b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/content.md new file mode 100644 index 0000000..5756de8 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/content.md @@ -0,0 +1,23 @@ +Welcome to the introductory course for the programming language C. +This course will show you the basic concepts of programming with more +or less practical examples, while not going to deep into the technical jargon. + +Programming is a usefull skill to automate all sorts of task, like evaluating data or controlling a system. +You can also write tools -- small or complex, to help you in your daily tasks or write fun stuff like games. +The more experience you have, the more incredible things you can program. + +At the end of this course, you should be able to write small programs, do some basic calculations and even program a virtual lift! + +So have some **fun** and don't be afraid to poke around. + +## Description of the online learning platform + +Before we start, we briefly describe this online learning platform. +This course is divided into topic related **sections** containing each several related **exercises**. + +In each exercise, we provide some introductory description, potentially with some external links for further reference and the actual **task** to perform. + +Press the *continue* button, to finish the current exercise in the section and proceed. +Alternatively, you may use the navigation bars on the left to navigate the **sections** and on the top to navigate the contained **exercises**. + +Now press *continue*. diff --git a/oer/courses/c-newcomers/sections/01-introduction/00-welcome/meta b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/c-newcomers/sections/01-introduction/00-welcome/type b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/00-welcome/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/c-newcomers/sections/01-introduction/01-programming/Makefile b/oer/courses/c-newcomers/sections/01-introduction/01-programming/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/01-programming/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/c-newcomers/sections/01-introduction/01-programming/content.md b/oer/courses/c-newcomers/sections/01-introduction/01-programming/content.md new file mode 100644 index 0000000..a313a26 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/01-programming/content.md @@ -0,0 +1,31 @@ +The first thing you probably want to know is: What is programming? +A program tells the computer what to do. +It is like writing a recipe: +You give the computer instructions to follow and the computer +just executes them in order to get the result. +_Remember_: The computer doesn't know what you try to achieve. It just does, what you tell him. + +## Description of the online learning platform (2) + +Below this text you see a text editor. The editor contains the program, i.e., the code to execute by the computer. In each exercise, we provide a basic skeleton for you to change and play with. +Now it contains your very first program. + +Below the editor are three buttons, **Execute** will tell the system to run your instructions and will output the results below. +**Submit results** tells the system to check if your program is correct. +Once the results were submitted correctly, you can press the **Continue** button. + +## Knowledge + +The source code is just some special text, which will get translated into executable code. +The line **int main()** in Line 3 tells the PC where your program starts. +Everything between the curly braces between Line 5 and 6 will be executed. +Everything behind two slashes "//" is a comment and will be ignored by the computer. +Thus, Line 5 will not cause any action by the computer. + +## Task + +For now the only instruction that will be executed is the line **printf("Hello NAME");** +This is a instruction to write the text between the quotes to the console, here "Hello Name". +Use the execute button to execute the code, do you see the output? +Then try the submit solution button to check the result: The provided code must be changed to be correct. +Change the program, such that it will display instead of NAME your actual name to greet you properly. diff --git a/oer/courses/c-newcomers/sections/01-introduction/01-programming/meta b/oer/courses/c-newcomers/sections/01-introduction/01-programming/meta new file mode 100644 index 0000000..34f304e --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/01-programming/meta @@ -0,0 +1 @@ +{"title": "Your first Program"} diff --git a/oer/courses/c-newcomers/sections/01-introduction/01-programming/program.c b/oer/courses/c-newcomers/sections/01-introduction/01-programming/program.c new file mode 100644 index 0000000..0238303 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/01-programming/program.c @@ -0,0 +1,7 @@ +#include //This is just a way to load in some functionality + +int main() // defines the start of your program +{ + // printf writes the text in quotes to the console + printf("Hello NAME"); // TODO change the text +} diff --git a/oer/courses/c-newcomers/sections/01-introduction/01-programming/regex b/oer/courses/c-newcomers/sections/01-introduction/01-programming/regex new file mode 100644 index 0000000..a6f7a8d --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/01-programming/regex @@ -0,0 +1 @@ +^Hello .*(? + +int main() +{ + printf("My BMI is %f", 0.0); // TODO: Replace the 0.0 with the calculation of your BMI +} diff --git a/oer/courses/c-newcomers/sections/01-introduction/02-bmi/regex b/oer/courses/c-newcomers/sections/01-introduction/02-bmi/regex new file mode 100644 index 0000000..f25e9c1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/02-bmi/regex @@ -0,0 +1 @@ +^My BMI is [1-9][0-9]*\.[0-9]*\s*$ diff --git a/oer/courses/c-newcomers/sections/01-introduction/02-bmi/type b/oer/courses/c-newcomers/sections/01-introduction/02-bmi/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/02-bmi/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/Makefile b/oer/courses/c-newcomers/sections/01-introduction/03-variables/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/content.md b/oer/courses/c-newcomers/sections/01-introduction/03-variables/content.md new file mode 100644 index 0000000..67b9cb6 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/content.md @@ -0,0 +1,32 @@ +As you could see, it is pretty simple to print out some basic calculations. +But sometimes you want do more complicated ones. +Then it is a good idea to save parts of the calculations in so called **variables**. + +## Knowledge + +Variables are like drawers, where you can store and label your solutions, but also update and replace them. +You then can use the name of the **variable** just like a number, +but it holds the data of what you have put into it before. + +To declare these variables you first write the type, e.g., +**float** for decimals and **int** for whole numbers, then the name of the variable. +This is needed that the computer can understand the program. +To assign a value to a variable, you write equals and then the value or mathematical expression it should compute before it assigns the data. + +A very simple example is: +``` +float x = 4.0; +float y = 3.0; +float result = x * y + 3.0; +``` + +You can also declare first what the variable is and then change it's value: +``` +float x; +x = 3.0; // now the value is 3.0 +x = 4.0; // now the value of x is 4.0 +``` + +## Task + +Your task is to rewrite the program to compute the BMI to use variables with height and weight. diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/meta b/oer/courses/c-newcomers/sections/01-introduction/03-variables/meta new file mode 100644 index 0000000..164f77a --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/meta @@ -0,0 +1 @@ +{"title": "BMI - Variables"} diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/program.c b/oer/courses/c-newcomers/sections/01-introduction/03-variables/program.c new file mode 100644 index 0000000..4393a1c --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/program.c @@ -0,0 +1,12 @@ +#include + +int main() +{ + // TODO: Fill in those Variables + float Weight = 0; + float Height = 0; + // TODO: use the variables Weight and Height to calculate the BMI and save it in a new variable + float bmi = 0; // add here the way how to compute the BMI + + printf("My BMI is %f", 0); // TODO: replace the 0 with the variable, which holds the BMI +} diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/regex b/oer/courses/c-newcomers/sections/01-introduction/03-variables/regex new file mode 100644 index 0000000..f25e9c1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/regex @@ -0,0 +1 @@ +^My BMI is [1-9][0-9]*\.[0-9]*\s*$ diff --git a/oer/courses/c-newcomers/sections/01-introduction/03-variables/type b/oer/courses/c-newcomers/sections/01-introduction/03-variables/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/03-variables/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/01-introduction/section b/oer/courses/c-newcomers/sections/01-introduction/section new file mode 100644 index 0000000..5437a09 --- /dev/null +++ b/oer/courses/c-newcomers/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Introduction", "description": "Writing Text to the Console"} diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/Makefile b/oer/courses/c-newcomers/sections/02-dice/01-dice/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/content.md b/oer/courses/c-newcomers/sections/02-dice/01-dice/content.md new file mode 100644 index 0000000..33b4241 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/content.md @@ -0,0 +1,21 @@ +We now move away from normal math calculations and move to the topic of random numbers. +Your task will be, to code a program, that rolls a dice and prints out the number. + +## Knowledge + +For that we need to include new functionality. To do that, we need to write: ``#include ;``. +In there are among other instructions **srand** and **rand**. +To call these instructions you have to put open and closed parentheses behind them. + +Because computers cannot create real random numbers but instead fake randomness with complex functions, we need to set a starting point for our **random number generator**, a so called seed that changes every time we call the program. +To do that we use the ``srand()`` instruction, which sets the seed of the random number generator. The only problem is, every time we run the program we would end up with the same result. +To avoid this we will also include the instruction time with ``#include `` to get the current time and pass that as the seed. + +We then can use ``rand()`` to get a random number. Because we only want numbers between 1 and 6, we have to use the modulo-operator %. +Don't worry, if you are not familiar with the math-concept of modulo. It just gives you the remainder of a whole number division. +So any number modulo 25 will give you a number between 0 and 24. + +## Task + +So that is all you need to know about random numbers. Now try to implement the dice program. + diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/execute.sh b/oer/courses/c-newcomers/sections/02-dice/01-dice/execute.sh new file mode 100755 index 0000000..185c136 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/execute.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./program diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/meta b/oer/courses/c-newcomers/sections/02-dice/01-dice/meta new file mode 100644 index 0000000..5444976 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/meta @@ -0,0 +1 @@ +{"title": "Roll a dice"} diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/program.c b/oer/courses/c-newcomers/sections/02-dice/01-dice/program.c new file mode 100644 index 0000000..e527cda --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/program.c @@ -0,0 +1,15 @@ +#include // printf +#include // rand and srand +#include // time + +int main() +{ + srand(time(0)); // seeding the random number generator with the current time + + // TODO: add some computation to restrict Number to 1-6 + // Because a dice has only whole numbers, we use int + int Number = rand(); + + + printf("You rolled a %d", Number); +} diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/test.sh b/oer/courses/c-newcomers/sections/02-dice/01-dice/test.sh new file mode 100755 index 0000000..5f724ea --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/test.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +pass=true +out="" +regex='^You rolled a [1-6]$' + +# figure out a way to make this more reliable +for i in {1..1} +do + sleep .15 + program_out=$(./program) + if [[ "$program_out" =~ $regex ]] + then + out="$out\nPASS $program_out" + else + pass=false + out="$out\nFAIL $program_out" + fi +done +if("$pass" = true) +then + echo PASS +else + echo FAIL +fi +echo "" +echo -e $out diff --git a/oer/courses/c-newcomers/sections/02-dice/01-dice/type b/oer/courses/c-newcomers/sections/02-dice/01-dice/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/01-dice/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/Makefile b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/content.md b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/content.md new file mode 100644 index 0000000..93fbdab --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/content.md @@ -0,0 +1,26 @@ +Rolling one dice isn't that exiting. Every side has the same chance. Now we want to roll two dice at the same time without writing the same code all over. +To do that, we use **functions**. + +## Knowledge + +Functions are like subprograms, which you can call. They look just like our main program. +You actually called functions before. Remember those more complex instructions like ``printf`` and ``rand``. +They were all functions. + +The first thing you have to write, is the **return type**. The return type tells the computer, what kind of value you function calculates and returns. +For our dice example this would be an **int**. There are also functions which return nothing. In that case the return type is **void**. + +Next comes the name. You can name your functions any name you like with a few restrictions. +After the name you write the **arguments** in parentheses. They also have a type and a name. The dice function doesn't need any arguments. +Between the curly braces comes your code. In the end you have to write **return** and behind that the value your function calculated. + +Here is an example of a simple add function: + + int add(int a, int b) + { + return a+b; + } + +## Task + +Your task is to implement the die function and call twice to simulate the rolling of two dice. diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/execute.sh b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/execute.sh new file mode 100755 index 0000000..185c136 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/execute.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./program diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/meta b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/meta new file mode 100644 index 0000000..be8ae2e --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/meta @@ -0,0 +1 @@ +{"title": "Roll two dice"} diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/program.c b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/program.c new file mode 100644 index 0000000..c5923a8 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/program.c @@ -0,0 +1,15 @@ +#include // printf +#include // rand and srand +#include // time + +//TODO: Write the dice function here + +int main() +{ + srand(time(0)); // you only have to set up your seed once + + int Number = (rand()%6)+1; + + // call the dice function and don't forget to add them together + printf("You rolled a %d",Number); +} diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/test.sh b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/test.sh new file mode 100755 index 0000000..dda7e00 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/test.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +pass=true +out="" +regex='^You rolled a (1[0-2]|[1-9])$' + +# figure out a way to test this more reliable +for i in {1..1} +do + sleep .15 + program_out=$(./program) + if [[ "$program_out" =~ $regex ]] + then + out="$out\nPASS $program_out" + else + pass=false + out="$out\nFAIL $program_out" + fi +done +if("$pass" = true) +then + echo PASS +else + echo FAIL +fi +echo "" +echo -e $out diff --git a/oer/courses/c-newcomers/sections/02-dice/02-2-dice/type b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/02-2-dice/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/Makefile b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/content.md b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/content.md new file mode 100644 index 0000000..9b644a5 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/content.md @@ -0,0 +1,54 @@ + + +Now, that you can roll two dice at the same time, let's try to do some statistics. +For that we need a way do something multiple times. In programming these constructs +are called loops. + +## Knowledge + +Loops may seem to have a convoluted syntax, but once you got it, it is straightforward. +First comes the keyword for, followed by open and closed parentheses. Then you set up your counter variable, +the condition, under which you stay in the loop and the instruction, which gets executed at the end, between the parentheses. + +
+
+

+ Definition of the for-loop +

for(initialization; condition; increment/decrement)
+{
+    // Looped code
+}
+

+ +
+
+

+ Here is an example of a loop with 10 iterations: +

for(int i = 0; i < 10; i=i+1)
+{
+    printf("We are in the %d. iteration", i+1);
+}
+

+
+
+ +* int i = 0 is the initialization and gets executed once at the beginning. It sets the iteration counter to zero. +* i < 10 is the condition. This gets checked every iteration in the beginning. If it is not true we skip over the loop. +* i=i+1; is the increment. This gets executed at the end of every iteration. This counts our up the iteration counter by one. You can also write i++ to achieve the same result. + +## Task + +Your task is the average of 100 rolls. + diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/meta b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/meta new file mode 100644 index 0000000..eb3be4f --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/meta @@ -0,0 +1 @@ +{"title": "Roll the dice multiple times"} diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/program.c b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/program.c new file mode 100644 index 0000000..7854dd6 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/program.c @@ -0,0 +1,21 @@ +#include // printf +#include // rand and srand +#include // time + +int roll_dice() +{ + return (rand()%6)+1; +} + +int main() +{ + srand(time(0)); + + // we don't care about the decimal places + int Average = 0; + + // TODO: execute this 100 times and calculate the average; + int value = roll_dice()+roll_dice(); + + printf("The average is %d", Average); +} diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/regex b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/regex new file mode 100644 index 0000000..38db6de --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/regex @@ -0,0 +1 @@ +^The average is [5-9]$ diff --git a/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/type b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/03-multible-rolls/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/Makefile b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/content.md b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/content.md new file mode 100644 index 0000000..6ec1b7d --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/content.md @@ -0,0 +1,21 @@ +The normal 6 sided dice is pretty boring. So how about rolling a D20 or a D8? +A D20 is a dice with 20 sides and a D8 one with 8. +But we don't want to write the function all over again. +You could also rewrite the dice function to take the amount of sides as a parameter. + +## Knowledge + +_Remember_: Parameters are written between the parentheses and are separated with commas. + +Like variables parameters have a type and a name. So when you have a function like: + + int add(int a, int b) + { + return a+b; + } + +and call it like this:`add(5+9);`, then a = 5 and b = 9 and it will return 14. + +## Task + +Rewrite the function, such that it take a parameter to determine, what kind of dice you roll. diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/meta b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/meta new file mode 100644 index 0000000..098c27b --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/meta @@ -0,0 +1 @@ +{"title": "D20 and D8"} diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/program.c b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/program.c new file mode 100644 index 0000000..0a7ab55 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/program.c @@ -0,0 +1,27 @@ +#include // printf +#include // rand and srand +#include // time + +// TODO: parameterise this +int roll_dice() +{ + return (rand()%6)+1; +} + +int main() +{ + srand(time(0)); + + // we don't care about the decimal places + int Average = 0; + + for (int i = 0; i < 1000; i++) + { + // TODO: use a D20 and a D8 + int Value = roll_dice()+roll_dice(); + Average = Average + Value; + } + Average = Average/1000; + + printf("The average is %d", Average); +} diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/regex b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/regex new file mode 100644 index 0000000..0281cf3 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/regex @@ -0,0 +1 @@ +^The average is 1[3-6]$ diff --git a/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/type b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/04-D20-D8/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/Makefile b/oer/courses/c-newcomers/sections/02-dice/05-distribution/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/content.md b/oer/courses/c-newcomers/sections/02-dice/05-distribution/content.md new file mode 100644 index 0000000..bb3b458 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/content.md @@ -0,0 +1,17 @@ +Calculating the average doesn't gives as much data, on how the probabilities for each outcome are distributed. +So let's compute the frequency distribution, which tells you for every possible outcome, how often it happend after some iterations. + +## Knowledge + +For that we need a new language construct: The array. An array is like the variables before. But now we talk about a set of variables. + +To declare an array you put open and closed braces behind the name with the number of elements behind it. +To access a single element you also put open and closed braces behind it with the number of the element you want to access. +So ``int array[6];`` declares an array of size six and ``array[0] = 42;`` sets the first element to 42. +The first element has always the index 0 and the last has an index of size-1. + +## Task + +Your task is to create an array with the appropriate size, to count up the frequency of each outcome. +The output of this program will be run through a [plotting program](http://www.gnuplot.info/). So when you hit the execute button, +you will see a text based graph of the distribution. diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/execute.sh b/oer/courses/c-newcomers/sections/02-dice/05-distribution/execute.sh new file mode 100755 index 0000000..66b4018 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/execute.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./program | gnuplot -e "set terminal dumb; set xtics 2; set mxtics 2; plot ' // printf +#include // rand and srand +#include // time + +int roll_dice(int Sides) +{ + return (rand()%Sides)+1; +} + +int main() +{ + // Init: + int FirstDice = 20; + int SeccondDice = 8; + + srand(time(0)); + + int Average = 0; + int Distribution[11]; //TODO: Set the right size. TIP: save the array size in a variable for later use + + // TODO: set all values of Distribution to zero using a for-loop + + // Calculate Distribution and Average + for (int i = 0; i < 100000; i++) + { + int Value = roll_dice(FirstDice)+roll_dice(SeccondDice); + + // TODO: count up the frequency of the Value. + // The smallest possible value 2 is supposed to be counted in index 0 + + Average = Average + Value; + } + Average = Average/100000; + + // Output code: + // TODO: adjust this to the array size + for(int i = 0; i < 6; i++) + { + printf("%d %d\n", i+2, Distribution[i]); + } +} diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/regex b/oer/courses/c-newcomers/sections/02-dice/05-distribution/regex new file mode 100644 index 0000000..c1c2f48 --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/regex @@ -0,0 +1 @@ +^(.|\s|\n)*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/test.sh b/oer/courses/c-newcomers/sections/02-dice/05-distribution/test.sh new file mode 100755 index 0000000..82c0efb --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/test.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +regex='^2 (.*?)28 (.*?)$' + +program_out=$(./program) +if [[ "$program_out" =~ $regex ]] +then + echo "PASS" $program_out +else + echo "FAIL " $program_out +fi + + diff --git a/oer/courses/c-newcomers/sections/02-dice/05-distribution/type b/oer/courses/c-newcomers/sections/02-dice/05-distribution/type new file mode 100644 index 0000000..25df91d --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/05-distribution/type @@ -0,0 +1 @@ +program/scriptgrade \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/02-dice/section b/oer/courses/c-newcomers/sections/02-dice/section new file mode 100644 index 0000000..b935eda --- /dev/null +++ b/oer/courses/c-newcomers/sections/02-dice/section @@ -0,0 +1 @@ +{"title": "Dice", "description": "A virtual dice to roll!"} diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/Makefile b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/content.md b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/content.md new file mode 100644 index 0000000..c40887f --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/content.md @@ -0,0 +1,17 @@ + Over the next few lectures you are going to build a simple lift controller. + Therefore, we will develop a virtual lift moving between the floors of a building with a given speed. + + This task consists of several subtasks that will be processed in the subsequent exercises. + During this process, we will develop and implement a model for the virtual lift. + +# Model + + **Time**: First, we'll have to simulate the progress of the lift over time. + The computer will have to remember the current time and perform some activity in the simulated lift. + We will simulate the timesteps with a for loop, which will count up the time. + + **Position of the lift**: The position of the lift is stored in the variable _CurrentFloor_. + When we move the lift, we either increment or decrement this variable. + +# Task + Your task is to write a loop, which iterates over 15 timesteps, whereas a timestep represends the amount of time it takes for the lift to go from one floor to the other. diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/meta b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/meta new file mode 100644 index 0000000..7815337 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/meta @@ -0,0 +1 @@ +{"title": "Timesteps"} diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/program.c b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/program.c new file mode 100644 index 0000000..88c488c --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/program.c @@ -0,0 +1,8 @@ +#include + +int main() +{ + int CurrentFloor = 0; + // TODO: wrap the next lines in the specified for loop + printf("I'm currently at floor %d\n", CurrentFloor); // \n means newline +} diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/regex b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/regex new file mode 100644 index 0000000..d4a76b9 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/regex @@ -0,0 +1 @@ +^.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/01-timesteps/type b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/01-timesteps/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/Makefile b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/content.md b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/content.md new file mode 100644 index 0000000..b84ae3b --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/content.md @@ -0,0 +1,7 @@ + Now, that we have a simple notion of time, we want to move the lift. For now only upwards. + This is still nothing new. But we want to make sure that we don't take to many steps at ones. + +# Task + + Your task is to simulate the lift moving upwards. + Simply increment the current floor each time-step. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/meta b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/meta new file mode 100644 index 0000000..533f9ff --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/meta @@ -0,0 +1 @@ +{"title": "Moving up"} diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/program.c b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/program.c new file mode 100644 index 0000000..9efc337 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/program.c @@ -0,0 +1,12 @@ +#include + +int main() +{ + int CurrentFloor = 0; + + for(int Timestep = 0; Timestep < 15; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + // TODO: increment the current floor + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/regex b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/regex new file mode 100644 index 0000000..0a67e28 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/regex @@ -0,0 +1 @@ +^.*0\n.*1\n.*2\n.*3\n.*4\n.*5\n.*6\n.*7\n.*8\n.*9\n.*10\n.*11\n.*12\n.*13\n.*14\n$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/02-moving-up/type b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/02-moving-up/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/Makefile b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/content.md b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/content.md new file mode 100644 index 0000000..1154099 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/content.md @@ -0,0 +1,71 @@ +Not every building has an infinit amount of floors. Our simulated building is supposed to have 10. +So it makes no sense to move to a floor higher than 10. +To encode that kind of behavior we need a new language feature. The if-statement. + +# Knowledge + +The if statement allows you to check, if a certain condition is met and only execute parts of your code if it is. + + if(condition) + { + // gets executed, if condition is true + } + else + { + // gets executed, if condition is false + } + +The else part is optional. + +To formulate a condition you need new operators. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OperatorMeaning
==True, when both sides are equal
!=True, when both side are not equal
<True, when left is less than right
>True, when left is bigger than right
<=True, when left is less than or equal to the right
>=True, when left is bigger or equal to the right
&&Only true, if both conditions are true
||True, when one condition is true
!negates the condition
+ +## Model + + Our model now has a top floor, which is safed in the conveniently named variable ``TopFloor``. + To represent that in the code you need to add a check if we already reached the top and react accordingly. + +## Task + + Your task is to check if the lift reached the top floor and change the direction to downwards. diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/meta b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/meta new file mode 100644 index 0000000..bafeec8 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/meta @@ -0,0 +1 @@ +{"title": "Limited Height"} diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/program.c b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/program.c new file mode 100644 index 0000000..5019e62 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/program.c @@ -0,0 +1,26 @@ +#include +#include //provides a boolean datatype bool to save the values true or false + +int main() +{ + int CurrentFloor = 0; + int TopFloor = 10; + + bool GoingUp = true; + + for(int Timestep = 0; Timestep < 15; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + if(GoingUp) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + // TODO: check if we reached the top floor and set the GoingUp variable to the appropiate value + // (true for up and false for down) + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/regex b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/regex new file mode 100644 index 0000000..bbafa20 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/regex @@ -0,0 +1 @@ +^.*0\n.*1\n.*2\n.*3\n.*4\n.*5\n.*6\n.*7\n.*8\n.*9\n.*10\n.*9\n.*8\n.*7\n.*6\n$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/type b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/03-smaller-building/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/Makefile b/oer/courses/c-newcomers/sections/03-lift/04-goal/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/content.md b/oer/courses/c-newcomers/sections/03-lift/04-goal/content.md new file mode 100644 index 0000000..bf828fa --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/content.md @@ -0,0 +1,11 @@ +Our Lift can now move up and down, but it still doesn't have any ability to move to a specific floor. + +## Model + +To represent that in the model, we added the variable ``TargetFloor``, which indicates to what floor the lift should move. +You have to check if the lift has to move up or down. +When the lift reached the target, it should stop for now. + +## Task + +Your task is to implement the movement to that floor. It should take the shortest route. When it reached the target, set the variable isDone to true. diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/meta b/oer/courses/c-newcomers/sections/03-lift/04-goal/meta new file mode 100644 index 0000000..cdf9341 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/meta @@ -0,0 +1 @@ +{"title": "Setting Goals"} diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/program.c b/oer/courses/c-newcomers/sections/03-lift/04-goal/program.c new file mode 100644 index 0000000..e2aa4bc --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/program.c @@ -0,0 +1,29 @@ +#include +#include + +int main() +{ + int CurrentFloor = 8; + int TargetFloor = 2; + + bool GoingUp = true; + bool isDone = false; + + for(int Timestep = 0; Timestep < 15 && !isDone; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + // TODO: replace this with a more apropiate logic + // for choosing the direction + if(GoingUp) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + // TODO: check if we reached the target floor and set the isDone variable to true + } + printf("I ended up in floor %d.", CurrentFloor); +} diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/regex b/oer/courses/c-newcomers/sections/03-lift/04-goal/regex new file mode 100644 index 0000000..cbfc33c --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/regex @@ -0,0 +1 @@ +^(.|\s)*I ended up in floor 2\.\s*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/04-goal/type b/oer/courses/c-newcomers/sections/03-lift/04-goal/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/04-goal/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/Makefile b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/content.md b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/content.md new file mode 100644 index 0000000..db99866 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/content.md @@ -0,0 +1,10 @@ +The lift can now reach exactly one target floor. But a lift can get more than one request. For now we only take a second one. + +## Model +So now our model is able to have multible targets. Basically a active one safed in ``TargetFloor`` and a secondary one saved in ``PendingFloor``. +This lift controller should prioritize the target floor first, but, if there is any pending floor that can be done one the way, it should stop there. +Otherwise you have to update the target floor. + +## Task + +Your task is to program that behavior. diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/meta b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/meta new file mode 100644 index 0000000..a43cb3e --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/meta @@ -0,0 +1 @@ +{"title": "Pending Floors"} diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/program.c b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/program.c new file mode 100644 index 0000000..ade36bf --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/program.c @@ -0,0 +1,41 @@ +#include +#include + +int main() +{ + int CurrentFloor = 8; + int TargetFloor = 2; + int PendingFloor = 6; + + bool reachedPendingFloor = false; + bool isDone = false; + + for(int Timestep = 0; Timestep < 15 && !isDone; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + + if(CurrentFloor < TargetFloor) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + // TODO: check, when you not reached the pending floor yet, + // if you reached it now, print out "I waited in floor " + + if(CurrentFloor == TargetFloor) + { + printf("I waited in floor %d.\n", CurrentFloor); + + // TODO: when you not reached the pending floor yet, + // set it to the target floor + + // TODO: set isDone and reachedPendingFloor appropriately + isDone = true; + } + + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/regex b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/regex new file mode 100644 index 0000000..7ec2913 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/regex @@ -0,0 +1 @@ +^(.|\s)*I waited in floor 6\.(\s|.)*I waited in floor 2\.\s*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/type b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/05-pending-goal/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/Makefile b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/content.md b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/content.md new file mode 100644 index 0000000..d461013 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/content.md @@ -0,0 +1,23 @@ +The lift controller is almost complete. It needs to be able to have more than just one pending floor and it needs a way to get new requests. +Let's concentrate on the first thing first. + +## Knowledge + +We already know how to speak in terms of multiple variables. We just use an array. +There are at least two reasonable solutions, on how to implement this array to encode the pending floors. +We could have an array, where each index stands for a floor and the value for whether or not the floor is pending. +The other way would be just a list of all the pending floors, **but** then we need a way of marking indices the lift already finished. +For example we could use the Value -1, this only works of course, if we don't have underground floors. + +## Model + +We think the first solution is a bit cleaner. So in our model we have the array, where every index is a floor. That way we also don't +have to worry about duplicates. The array in question is called ``PendingFloors``. + +Because we have more pending floors, we now also have to check if we reached all, if not we have to keep going. And on every level we have to +check if the floor we are on is a pending floor. + +## Task + +Change the program to support multiple pending floors. When choosing the next target floor, use the first not finished floor from the pending floor array. +The lift will **not** reach every floor, because we don't simulate enough time-steps. diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/meta b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/meta new file mode 100644 index 0000000..9a62e77 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/meta @@ -0,0 +1 @@ +{"title": "More Requests"} diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/program.c b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/program.c new file mode 100644 index 0000000..db14945 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/program.c @@ -0,0 +1,61 @@ +#include +#include + +int main() +{ + int CurrentFloor = 8; + int TargetFloor = 2; + bool PendingFloors[10] = {}; + PendingFloors[0] = true; // Floor 1 + PendingFloors[2] = true; // Floor 3 + PendingFloors[5] = true; // Floor 6 + PendingFloors[7] = true; // Floor 8 + PendingFloors[9] = true; // Floor 10 + + bool reachedAllPendingFloors = false; + bool isDone = false; + + for(int Timestep = 0; Timestep < 15 && !isDone; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + + if(CurrentFloor < TargetFloor) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + // TODO: Check for the correct pending floor + if(!reachedAllPendingFloors && CurrentFloor == PendingFloors[0]) + { + printf("I waited in floor %d.\n", CurrentFloor); + // TODO: change this to only set the index to finished + reachedAllPendingFloors = true; + } + + // TODO: check if there are any more pending floors left and set + // reachedAllPendingFloors appropriately + + if(CurrentFloor == TargetFloor) + { + printf("I waited in floor %d.\n", CurrentFloor); + + if(!reachedAllPendingFloors) + { + // TODO: get the first floor that isn't finished yet. + // TIP: the break keyword allows you to stop a loop + TargetFloor = PendingFloors[0]; + // TODO: change this to only indicate, that the new target floor is no pending floor anymore + reachedAllPendingFloors = true; + } + else + { + isDone = true; + } + } + + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/regex b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/regex new file mode 100644 index 0000000..d9b93f1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/regex @@ -0,0 +1 @@ +^(.|\s)*I waited in floor 6\.(\s|.)*I waited in floor 3\.(\s|.)*I waited in floor 2\.(\s|.)*I waited in floor 8\.(\s|.)*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/06-more-requests/type b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/06-more-requests/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/Makefile b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/content.md b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/content.md new file mode 100644 index 0000000..94f6b94 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/content.md @@ -0,0 +1,12 @@ +Because a lift can take request while it is running, let's simmulate getting one request for each timestep. + +## Model + +For this we prepared a list of request, which should only be applyed to the pending requests one by one. +The request are stored in the array ``RequestsOverTime``, where each index stands for one time-step. +So each time-step you need to look at the appropriate request and set the pending floor accordingly. +As with last time, the lift will not be able to visit all the floors, because we simulate not enough time-steps. + +## Task + +Implement the applying of requests over time. diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/meta b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/meta new file mode 100644 index 0000000..4553200 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/meta @@ -0,0 +1 @@ +{"title": "Requests Over Time"} diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/program.c b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/program.c new file mode 100644 index 0000000..0f7d902 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/program.c @@ -0,0 +1,72 @@ +#include +#include + +int main() +{ + int CurrentFloor = 8; + int TargetFloor = 2; + int RequestsOverTime[15] = {2,6,1,8,10,5,3,2,10,7,8,4,5,1,7}; + int PendingFloors[10] = {}; + + bool reachedAllPendingFloors = false; + bool isDone = false; + + for(int Timestep = 0; Timestep < 15 && !isDone; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + // TODO: Take the next Request from RequestOverTime and put it into the PendingFloors array + // at the index of the timestep + + if(CurrentFloor < TargetFloor) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + bool foundFloor = false; + if(!reachedAllPendingFloors && PendingFloors[CurrentFloor]) + { + + printf("I waited in floor %d.\n", CurrentFloor); + PendingFloors[CurrentFloor] = false; + foundFloor = true; + } + + reachedAllPendingFloors = true; + for(int i = 0; i < 15; i++) + { + if(PendingFloors[i] != false) + { + reachedAllPendingFloors = false; + break; + } + } + + if(CurrentFloor == TargetFloor) + { + if(!foundFloor) + printf("I waited in floor %d.\n", CurrentFloor); + + if(!reachedAllPendingFloors) + { + for(int i = 0; i < 15; i++) + { + if(PendingFloors[i] != false) + { + TargetFloor = PendingFloors[i]; + PendingFloors[i] = false; + break; + } + } + } + else + { + isDone = true; + } + } + + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/regex b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/regex new file mode 100644 index 0000000..d9b93f1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/regex @@ -0,0 +1 @@ +^(.|\s)*I waited in floor 6\.(\s|.)*I waited in floor 3\.(\s|.)*I waited in floor 2\.(\s|.)*I waited in floor 8\.(\s|.)*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/type b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/07-requests-over-time/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/Makefile b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/content.md b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/content.md new file mode 100644 index 0000000..0405ced --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/content.md @@ -0,0 +1,11 @@ +That's were all the task for the simple lift controller. Below you find a solution for the last task. +But there is always room for improvements. Here are just some examples one could do to improve or expand the lift controller: + +* Use more appropriate data structures like a queue +* Parsing the command-line arguments to determine the requests +* Change it to work with arbitrary amounts of time-steps +* Implement different phases like moving to a different floor and waiting at a floor with a State Machine + +This is just some ideas we have you could try, if you gathered more experience. For that you could try out the C-Basic course or find +coding resources on your own. + diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/meta b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/meta new file mode 100644 index 0000000..649dfae --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/meta @@ -0,0 +1 @@ +{"title": "Completed Lift"} diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/program.c b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/program.c new file mode 100644 index 0000000..8ca1aca --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/program.c @@ -0,0 +1,74 @@ +#include +#include + +int main() +{ + int CurrentFloor = 8; + int TargetFloor = 2; + int RequestOverTime[15] = {2,6,1,8,10,5,3,2,10,7,8,4,5,1,7}; + int PendingFloors[10] = {}; + + bool reachedAllPendingFloors = false; + bool isDone = false; + + for(int Timestep = 0; Timestep < 15 && !isDone; Timestep++) + { + printf("I'm currently at floor %d\n", CurrentFloor); + PendingFloors[RequestOverTime[Timestep]] = true; + + if(CurrentFloor < TargetFloor) + { + CurrentFloor++; + } + else + { + CurrentFloor--; + } + + bool foundFloor = false; + if(!reachedAllPendingFloors) + { + + if(CurrentFloor == PendingFloors[CurrentFloor]) + { + foundFloor = true; + PendingFloors[CurrentFloor] = false; + printf("I waited in floor %d.\n", CurrentFloor); + } + } + + reachedAllPendingFloors = true; + for(int i = 0; i < 15; i++) + { + if(PendingFloors[i] != false) + { + reachedAllPendingFloors = false; + break; + } + } + + if(CurrentFloor == TargetFloor) + { + if(!foundFloor) + printf("I waited in floor %d.\n", CurrentFloor); + + if(!reachedAllPendingFloors) + { + for(int i = 0; i < 15; i++) + { + if(PendingFloors[i] != false) + { + TargetFloor = PendingFloors[i]; + PendingFloors[i] = false; + break; + } + } + } + else + { + isDone = true; + } + } + + } +} diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/regex b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/regex new file mode 100644 index 0000000..d9b93f1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/regex @@ -0,0 +1 @@ +^(.|\s)*I waited in floor 6\.(\s|.)*I waited in floor 3\.(\s|.)*I waited in floor 2\.(\s|.)*I waited in floor 8\.(\s|.)*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/type b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/08-complete-lift/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/03-lift/section b/oer/courses/c-newcomers/sections/03-lift/section new file mode 100644 index 0000000..647bf22 --- /dev/null +++ b/oer/courses/c-newcomers/sections/03-lift/section @@ -0,0 +1 @@ +{"title": "Lift", "description": "A simple lift controller"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/content.md b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/content.md new file mode 100644 index 0000000..41e7073 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/content.md @@ -0,0 +1,30 @@ +The next exercises will focus around simulating a supermarket with multiple customers and multiple queues. +In contrast to the lift-course we will not simulate a fixed amount of time. Instead we will simulate +until all customers are served. + +## Model + +As with the lift we will take tiny steps and will increase the complexity of the model bit by bit. +Our end goal is to have a bunch of customers with different items, which all take different amounts of time to scan, +which will be served by multiple cashiers. + +To get there we start with only one customer and one cashier. Each item should take the same amount of time. +To do that, we keep track of the item count in the Variable ``CustomerItemCount``. +When one gets processed we simply need do decrement that value. + +## Knowledge + +Because we don't want a fixed amount of time steps, like we did with the lift, we need a different kind of _loop_. +A **while-loop** loops as long as its condition is true. + + while(condition) + { + // looped code here + } + +This is exactly what we need to serve all customers until no one is left or for now until all items are gone. + +## Task + +For now your task will be to implement one cashier and one customer with 5 items. +Each item should take the same amount of time for now. diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/meta b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/meta new file mode 100644 index 0000000..31398ce --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/meta @@ -0,0 +1 @@ +{"title": "Customer and Cashier"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/program.c b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/program.c new file mode 100644 index 0000000..6d84633 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/program.c @@ -0,0 +1,25 @@ +#include +#include + +int main() +{ + bool CustomerHasItems = true; + int CustomerItemCount = 5; + + /* + * This is a while loop. + * It functions similar to the for-loop, + * but, instead of counting up a variable, it only + * checks for the condition. + */ + while(CustomerHasItems) + { + // TODO: Process the items + printf("Scanning a product. %d to go.\n", CustomerItemCount); + + // TODO: check if there are still items to process + // and set CustomerHasItems appropriately + CustomerHasItems = false; + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/regex b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/regex new file mode 100644 index 0000000..9441f20 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/regex @@ -0,0 +1 @@ +(.|\s)*Scanning a product\. 0 to go\.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/type b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/01-while-loop/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/content.md b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/content.md new file mode 100644 index 0000000..b5d8ea1 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/content.md @@ -0,0 +1,45 @@ +Now that the cashier can scan items, the next step will be to have different items which take different amount of time. + +## Model + +In our model we now not only have to track the amount of items, but also the type. The items of the customer are stored in the ``CustomerItems`` array. +You could have stored each item type as a different number, but this gets confusing and hard to maintain. Thats why we used an enum. We talk about how enums work later. + +To model the time each of these item needs, we have an array ``Time``, which associates with each item type a unique time. + +Now that items take different amounts of time, it gets interessting how long the whole scanning process took. For that we update the time in the variable ``TimePassed``. +The time is counted in secconds. + +## Knowledge + +Know back to how enums work. An enum is a way to declare new types. In the background it only binds a number to a name. This makes your code more readable and easier to change, +because the numbers are automatically generated. It doesn't matter if you add one member or delete one or change the order. + +Here is an example of an enum for food types. + + typedef enum + { + Burger, + Pizza, + Steak, + Salad, + Porkchop, + + Food_type_count, + }food; + +The last line ``Food_type_count`` is a nice trick to get the amount of members of an enum. This only works because the compiler, the program which translates your code into machine readable code, +just counts up the numbers. In this case Burger is 0 and Pizza is 1 ... and Food_type_count is 5; +You could then use this for example to associate a kcal-value to them with an array. + + food kcal[Food_type_count]; + kcal[Burger] = 600; + kcal[Salad] = 150; + +etc. + +This may not be the most elegant solution, but it is a pretty simple one. + +## Task + +Your task is to implement the items enum and update the amount of time depending on the scanned item. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/meta b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/meta new file mode 100644 index 0000000..7eb7f67 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/meta @@ -0,0 +1 @@ +{"title": "Item Types"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/program.c b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/program.c new file mode 100644 index 0000000..46de00b --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/program.c @@ -0,0 +1,36 @@ +#include +#include + +// TODO: implement the item enum + +int main() +{ + bool CustomerHasItems = true; + int TimePassed = 0; + +#define CUSTOMER_ITEM_COUNT 5 // This declares a constant + item CustomerItems[CUSTOMER_ITEM_COUNT] = {tissues, pasta, tomato_sauce, bread, butter}; + + // NOTE: time is in seconds + item Time[ITEM_TYPE_COUNT]; + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; + + int ItemsLeft = CUSTOMER_ITEM_COUNT; + while(CustomerHasItems) + { + // TODO: increase time based on the scaned item + TimePassed++; + ItemsLeft--; + printf("Time since start: %d. Scanning a product. %d to go.\n", TimePassed, ItemsLeft); + + if(!ItemsLeft) + CustomerHasItems = false; + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/regex b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/regex new file mode 100644 index 0000000..03fdaa7 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/regex @@ -0,0 +1 @@ +^(.|\s)*Time since start: 18\. Scanning a product\. 0 to go\.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/02-enums/type b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/02-enums/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/03-states/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/content.md b/oer/courses/c-newcomers/sections/04-supermarket/03-states/content.md new file mode 100644 index 0000000..13abb85 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/content.md @@ -0,0 +1,35 @@ +This is great. Each item can now take different amounts of time to be scanned, but when you have multiple cashiers, +one can scan many "easy" items, while the other scans one slowly. So simply adding up the time won't cut it. + +To prepare the program for more than one cashier, this needs to change. To stay on the topics of enums we +will use a construct known as a [finite-state-machine](https://en.wikipedia.org/wiki/Finite-state_machine). + +## Knowledge + +A finite-state-machine let's you easily define different behaviours depending on what state their are in. +Basically you need a variable to track the state, in this case it is ``CurrentState`` and you need a way of +implementing different behaviour based on the current state. For that you can simply use if statements. + +If you have more than one condition you want to test on, for example three different states, +you can use the **else if** statement. This allows you to first test if one thing is true and, if is not, +you can test for the second condition. You can chain as many else if statements as you want. + + if(condition1) + { + // gets executed if condition 1 is true + } + else if(condition2) + { + // gets executed if condition1 is false and condition2 is true + } + else + { + // gets executed if non of the conditions above are true + } + +So our cashier has the state STATE_ready_for_item and STATE_scanning. These are represented as an enum. + +## Task + +Your task will be to implement the state-machine with an enum, such that while scanning +you only increment the time-step by one. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/meta b/oer/courses/c-newcomers/sections/04-supermarket/03-states/meta new file mode 100644 index 0000000..c6d1282 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/meta @@ -0,0 +1 @@ +{"title": "States"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/program.c b/oer/courses/c-newcomers/sections/04-supermarket/03-states/program.c new file mode 100644 index 0000000..b13ca77 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/program.c @@ -0,0 +1,59 @@ +#include +#include + +typedef enum +{ + STATE_ready_for_item, + STATE_scanning, +}state; + +typedef enum +{ + tissues, + pasta, + tomato_sauce, + bread, + butter, + batteries, + toothbrush, + + ITEM_TYPE_COUNT, +}item; + +int main() +{ + bool CustomerHasItems = true; + int TimePassed = 0; + +#define CUSTOMER_ITEM_COUNT 5 // This declares a constant + item CustomerItems[CUSTOMER_ITEM_COUNT] = {tissues, pasta, tomato_sauce, bread, butter}; + + // NOTE: time is in seconds + item Time[ITEM_TYPE_COUNT]; + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; + + int ItemsLeft = CUSTOMER_ITEM_COUNT; + state CurrentState = STATE_ready_for_item; // The state the cashier is in + while(CustomerHasItems) + { + // TODO: Implement the state machine here + int CurrentItemIndex = CUSTOMER_ITEM_COUNT - ItemsLeft; + item CurrentItem = CustomerItems[CurrentItemIndex]; + + TimePassed += Time[CurrentItem]; + ItemsLeft--; + + // Print this only while scanning + printf("Time since start: %d. Scanning a product. %d to go.\n", TimePassed, ItemsLeft); + + if(!ItemsLeft) + CustomerHasItems = false; + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/regex b/oer/courses/c-newcomers/sections/04-supermarket/03-states/regex new file mode 100644 index 0000000..5210f36 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/regex @@ -0,0 +1 @@ +^(.*\n){17,18}Time since start: 18. Scanning a product. 0 to go.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/03-states/type b/oer/courses/c-newcomers/sections/04-supermarket/03-states/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/03-states/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/content.md b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/content.md new file mode 100644 index 0000000..203da62 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/content.md @@ -0,0 +1,34 @@ +You prepared the cashier for the step to multiple cashiers. But let's not go there yet. +First you should flesh out the concept of a customer. + +## Model + +In our model the customer should have a list of items he buys, but you could add more things to make it more interesting. +For example some customers pack their items painfully slow and some really fast. So let's add that too. +So the scanning phase takes the amount of time of the item plus the packing-speed. + +## Knowledge + +For that we need a new language construct. The struct. +A struct works similar to an enum, but instead counting up numbers, you basically packing +multiple variables together to build more complex data-types. + +Here is an example of a struct for a person: + + typedef struct + { + char *Name; // This is some Text + int Age; + + gender Gender; // This is an enum + }person; + +If you want to access a member of the struct you write first the name of the variable containing the struct, then a dot and then the name of the member. +For example we have a variable Bob ``person Bob`` and want to assign him an age of 35 ``Bob.age = 35``. + +Because the file got a little big, we pulled out some of the definitions like the enums into a +header file and included it with the command `#include "supermarket.h"`. + +## Task + +Your task is to implement a struct for the customer and take the packing speed into account. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/meta b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/meta new file mode 100644 index 0000000..6441171 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/meta @@ -0,0 +1 @@ +{"title": "Customer"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/program.c b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/program.c new file mode 100644 index 0000000..8035634 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/program.c @@ -0,0 +1,57 @@ +#include +#include +#include "supermarket.h" + +#define CUSTOMER_ITEM_COUNT 5 +// TODO: Implement the struct here with an array of 5 items and a packing speed + +int main() +{ + bool CustomerHasItems = true; + int TimePassed = 0; + + // TODO: replace this with a your struct and add a packing speed of 2 + item CustomerItems[CUSTOMER_ITEM_COUNT] = {tissues, pasta, tomato_sauce, bread, butter}; + + // NOTE: To access a member of your customer struct you have to use the .-operator + // e.g Customer.PackingSpeed = 23; + + // NOTE: the Time-array is now a global Variable + initTimeTable(); + + int ItemsLeft = CUSTOMER_ITEM_COUNT; + state CurrentState = STATE_ready_for_item; + int TimeToScan = 0; + while(CustomerHasItems) + { + if(CurrentState == STATE_ready_for_item) + { + int CurrentItemIndex = CUSTOMER_ITEM_COUNT - ItemsLeft; + + // TODO: Change this to use the customer struct + item CurrentItem = CustomerItems[CurrentItemIndex]; + + // TODO: add the packing speed on top of the scanning time + TimeToScan = Time[CurrentItem]; + CurrentState = STATE_scanning; + } + else + { + TimePassed ++; + TimeToScan --; + + if (TimeToScan == 0) + { + ItemsLeft--; + CurrentState = STATE_ready_for_item; + } + printf("Time since start: %d. Scanning a product. %d to go.\n", TimePassed, ItemsLeft); + + } + + + if(!ItemsLeft) + CustomerHasItems = false; + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/regex b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/regex new file mode 100644 index 0000000..1fbecda --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/regex @@ -0,0 +1 @@ +^(.*\n){27,28}Time since start: 28. Scanning a product. 0 to go.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/supermarket.h b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/supermarket.h new file mode 100644 index 0000000..5e88b1a --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/supermarket.h @@ -0,0 +1,31 @@ +typedef enum +{ + STATE_ready_for_item, + STATE_scanning, +}state; + +typedef enum +{ + tissues, + pasta, + tomato_sauce, + bread, + butter, + batteries, + toothbrush, + + ITEM_TYPE_COUNT, +}item; + +item Time[ITEM_TYPE_COUNT]; + +void initTimeTable() +{ + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/04-customer/type b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/04-customer/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/content.md b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/content.md new file mode 100644 index 0000000..21b2fc5 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/content.md @@ -0,0 +1,12 @@ +Now that we fleshed out the notion of what a customer is, it is easier to create more than one. +In fact for this task we already made an array of multiple customers. + +## Model + +In our model we now have an array with different customers to be served. +But we now have to handle the case, where the cashier gets a new customer. +For that we added a new state STATE_ready_for_customer + +## Task + +Your task is to implement, that, if a customer is finished, the cashier gets a new one. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/meta b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/meta new file mode 100644 index 0000000..4856a80 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/meta @@ -0,0 +1 @@ +{"title": "Customers"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/program.c b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/program.c new file mode 100644 index 0000000..2f35a3f --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/program.c @@ -0,0 +1,81 @@ +#include +#include +#include "supermarket.h" + +#define CUSTOMER_ITEM_COUNT 5 +typedef struct +{ + item Items[CUSTOMER_ITEM_COUNT]; + int PackingSpeed; +}customer; + +int main() +{ + bool CustomersLeft = true; + int TimePassed = 0; + + // NOTE: the {...} syntax is an easy way to initialize structs + customer CustomerQueue[3] = + { + { + {tissues, pasta, tomato_sauce, bread, butter}, + 2 + }, + { + {toothbrush, batteries, bread, bread, butter}, + 3 + }, + { + {bread, batteries, tomato_sauce, pasta, tissues}, + 9 + } + }; + int NextQueueIndex = 0; + + initTimeTable(); + + int ItemsLeft = CUSTOMER_ITEM_COUNT; + int TimeToScan = 0; + + state CurrentState = STATE_ready_for_customer; + int CurrentCustomer = 0; + int CurrentItemIndex; + while(CustomersLeft) + { + if(CurrentState == STATE_ready_for_item) + { + // TODO: check if there are items left + // if not, change to the STATE_ready_for_customer state + // and don't forget to reset ItemsLeft + CurrentItemIndex = CUSTOMER_ITEM_COUNT - ItemsLeft; + item CurrentItem = CustomerQueue[CurrentCustomer].Items[CurrentItemIndex]; + + TimeToScan = Time[CurrentItem] + CustomerQueue[CurrentCustomer].PackingSpeed; + CurrentState = STATE_scanning; + } + else if (CurrentState == STATE_scanning) + { + TimePassed ++; + TimeToScan --; + + if (TimeToScan == 0) + { + ItemsLeft--; + CurrentState = STATE_ready_for_item; + // NOTE: we moved the printf inside so the console doesn't get spammed with messages + printf("Time since start: %ds. Scanned product %d. %d to go.\n", TimePassed, CurrentItemIndex, ItemsLeft); + } + + } + else // NOTE: we added the state STATE_ready_for_customer + { + // TODO: implement this. + // don't forget to check if there are any customers left and to change + // the state + printf("Currently serving customer %d\n", CurrentCustomer); + CustomersLeft = false; + } + + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/regex b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/regex new file mode 100644 index 0000000..c851b70 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/regex @@ -0,0 +1 @@ +^.*customer 0(.*\n){6}.*customer 1(.*\n){6}.*customer 2(.*\n){5}Time since start: 131..*0 to go.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/solution.c b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/solution.c new file mode 100644 index 0000000..ff356f9 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/solution.c @@ -0,0 +1,88 @@ +;; This buffer is for text that is not saved, and for Lisp evaluation. +;; To create a file, visit it with C-x C-f and enter text in its buffer. + +#include +#include +#include "supermarket.h" + +#define CUSTOMER_ITEM_COUNT 5 +typedef struct +{ + item Items[CUSTOMER_ITEM_COUNT]; + int PackingSpeed; +}customer; + +int main() +{ + bool CustomersLeft = true; + int TimePast = 0; + + customer CustomerQueue[3] = { + + // NOTE: the {...} syntax is an easy way to initialize structs + { + {tissues, pasta, tomato_sauce, bread, butter}, + 2 + }, + { + {toothbrush, batteries, bread, bread, butter}, + 3 + }, + { + {bread, batteries, tomato_sauce, pasta, tissues}, + 9 + } + }; + int NextQueueIndex = 0; + + initTimeTable(); + + int ItemsLeft = CUSTOMER_ITEM_COUNT; + state CurrentState = STATE_ready_for_customer; + int CurrentCustomer = 0; + int TimeToScan = 0; + while(CustomersLeft) + { + if(CurrentState == STATE_ready_for_item) + { + if(ItemsLeft > 0) + { + int CurrentItemIndex = CUSTOMER_ITEM_COUNT - ItemsLeft; + item CurrentItem = CustomerQueue[CurrentCustomer].Items[CurrentItemIndex]; + + TimeToScan = Time[CurrentItem] + CustomerQueue[CurrentCustomer].PackingSpeed; + CurrentState = STATE_scanning; + } + else + { + CurrentState = STATE_ready_for_customer; + } + } + else if (CurrentState == STATE_scanning) + { + TimePast ++; + TimeToScan --; + + if (TimeToScan == 0) + { + ItemsLeft--; + CurrentState = STATE_ready_for_item; + } + printf("Time since start: %d. Scanning a product. %d to go.\n", TimePast, ItemsLeft); + + } + else + { + if(NextQueueIndex < 3) + { + CurrentCustomer = NextQueueIndex++; + CurrentState = STATE_ready_for_items; + } + else + { + CustomersLeft = false; + } + } + } + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/supermarket.h b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/supermarket.h new file mode 100644 index 0000000..c175816 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/supermarket.h @@ -0,0 +1,32 @@ +typedef enum +{ + STATE_ready_for_item, + STATE_ready_for_customer, + STATE_scanning, +}state; + +typedef enum +{ + tissues, + pasta, + tomato_sauce, + bread, + butter, + batteries, + toothbrush, + + ITEM_TYPE_COUNT, +}item; + +item Time[ITEM_TYPE_COUNT]; + +void initTimeTable() +{ + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/05-customers/type b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/05-customers/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/content.md b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/content.md new file mode 100644 index 0000000..c89fd57 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/content.md @@ -0,0 +1,15 @@ +Our next goal is to have multiple cashiers, so we can serve multiple customers at ones. +Because this is kind of a big step, we will break it down to two smaller exercises. + +The first step is to put all the variables for the cashier-state-machine into a struct and +pull out the code into a function (let's call it step). This kind of code change, which doesn't +change the behavior of your program, is called refactoring. + +This may seem like a lot of busy work, but it is really important. Specially if you want to reuse code. + +Don't be discouraged, if you get a ton of error-messages. This is normal for this kind of work. +Just read them carefully one by one and fix them. + +If this seems to you as to much code change at ones, just take your time and do one TODO at the time. + +Your task is to refactor the cashier code. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/meta b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/meta new file mode 100644 index 0000000..18474ff --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/meta @@ -0,0 +1 @@ +{"title": "Refactor the Cashier"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/program.c b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/program.c new file mode 100644 index 0000000..b9b5b3b --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/program.c @@ -0,0 +1,80 @@ +#include +#include +#include "supermarket.h" + +// NOTE: these need to be global now, because the step function needs to edit them. +bool CustomersLeft = true; +int TimePassed = 0; +int NextQueueIndex; + +// TODO: define the cashier struct here + +// TODO: declare your cashier here as a global variable + +// TODO: define the step function here + +int main() +{ + // NOTE: CustomerQueue is now a global Variable + InitCustomerQueue(); + + initTimeTable(); + NextQueueIndex = 0; + + // TODO: move this to the cashier struct + //----- + int TimeToScan = 0; + state CurrentState = STATE_ready_for_customer; + int CurrentCustomer = 0; + int CurrentItemIndex; + //----- + + // NOTE: we change the program to compute ItemsLeft instead of keeping it in a varriable + while(CustomersLeft) + { + // TODO: refactor this code to the step function + if(CurrentState == STATE_ready_for_item) + { + if(CurrentItemIndex < CUSTOMER_ITEM_COUNT) + { + item CurrentItem = CustomerQueue[CurrentCustomer].Items[CurrentItemIndex]; + + TimeToScan = Time[CurrentItem] + CustomerQueue[CurrentCustomer].PackingSpeed; + CurrentState = STATE_scanning; + } + else + { + CurrentState = STATE_ready_for_customer; + } + } + else if (CurrentState == STATE_scanning) + { + TimePassed ++; + TimeToScan --; + + if (TimeToScan == 0) + { + CurrentItemIndex++; + CurrentState = STATE_ready_for_item; + printf("Time since start: %ds. Scanned product %d. %d to go.\n", + TimePassed, CurrentItemIndex, + CUSTOMER_ITEM_COUNT-CurrentItemIndex); + } + + } + else + { + if(NextQueueIndex < 3) + { + CurrentCustomer = NextQueueIndex++; + CurrentState = STATE_ready_for_item; + CurrentItemIndex = 0; + printf("Currently serving customer %d.\n", CurrentCustomer); + } + else + { + CustomersLeft = false; + } + } + } +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/regex b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/regex new file mode 100644 index 0000000..c851b70 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/regex @@ -0,0 +1 @@ +^.*customer 0(.*\n){6}.*customer 1(.*\n){6}.*customer 2(.*\n){5}Time since start: 131..*0 to go.$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/supermarket.h b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/supermarket.h new file mode 100644 index 0000000..410a8bf --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/supermarket.h @@ -0,0 +1,65 @@ +typedef enum +{ + STATE_ready_for_item, + STATE_ready_for_customer, + STATE_scanning, + STATE_finished, +}state; + +typedef enum +{ + tissues, + pasta, + tomato_sauce, + bread, + butter, + batteries, + toothbrush, + + ITEM_TYPE_COUNT, +}item; + +item Time[ITEM_TYPE_COUNT]; + +void initTimeTable() +{ + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; +} +#define CUSTOMER_ITEM_COUNT 5 +typedef struct +{ + item Items[CUSTOMER_ITEM_COUNT]; + int PackingSpeed; +}customer; + +customer CustomerQueue[3]; +void InitCustomerQueue() +{ + CustomerQueue[0].Items[0] = tissues; + CustomerQueue[0].Items[1] = pasta; + CustomerQueue[0].Items[2] = tomato_sauce; + CustomerQueue[0].Items[3] = bread; + CustomerQueue[0].Items[4] = butter; + CustomerQueue[0].PackingSpeed = 2; + + CustomerQueue[1].Items[0] = toothbrush; + CustomerQueue[1].Items[1] = batteries; + CustomerQueue[1].Items[2] = bread; + CustomerQueue[1].Items[3] = bread; + CustomerQueue[1].Items[4] = butter; + CustomerQueue[1].PackingSpeed = 3; + + CustomerQueue[2].Items[0] = bread; + CustomerQueue[2].Items[1] = batteries; + CustomerQueue[2].Items[2] = tomato_sauce; + CustomerQueue[2].Items[3] = pasta; + CustomerQueue[2].Items[4] = tissues; + CustomerQueue[2].PackingSpeed = 9; + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/type b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/06-refactor-cashier/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/Makefile b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/Makefile new file mode 100644 index 0000000..1f05f47 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/Makefile @@ -0,0 +1,4 @@ +all: + gcc program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/content.md b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/content.md new file mode 100644 index 0000000..a87022e --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/content.md @@ -0,0 +1,5 @@ +Now to the seccond step. Instead of one cashier we want to make 2 cashiers. +For that we need an array, which holds the cashiers and we need to change +the step function to work on said array. + +Your task is to do exactly that. \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/meta b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/meta new file mode 100644 index 0000000..2e483e4 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/meta @@ -0,0 +1 @@ +{"title": "Multiple Cashiers"} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/program.c b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/program.c new file mode 100644 index 0000000..e059704 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/program.c @@ -0,0 +1,93 @@ +#include +#include +#include "supermarket.h" + +int FinishedCashiers = 0; +int TimePassed = 0; +int NextQueueIndex; + +typedef struct +{ + state CurrentState; + int CurrentCustomer; + int CurrentItemIndex; + + int TimeToScan; +}cashier; + +// TODO: Change this number to 2 after you changed the step function +#define CASHIER_COUNT 1 + +// TODO: Changes this to an array of 2 cashiers +cashier Cashier = {STATE_ready_for_customer, 0, 0, 0}; + +// TODO: Changes this to use the index of the cashier +void step(int Index) +{ + if(Cashier.CurrentState == STATE_ready_for_item) + { + if(Cashier.CurrentItemIndex < CUSTOMER_ITEM_COUNT) + { + item CurrentItem = CustomerQueue[Cashier.CurrentCustomer].Items[Cashier.CurrentItemIndex]; + Cashier.TimeToScan = Time[CurrentItem] + CustomerQueue[Cashier.CurrentCustomer].PackingSpeed; + Cashier.CurrentState = STATE_scanning; + } + else + { + Cashier.CurrentState = STATE_ready_for_customer; + } + } + else if (Cashier.CurrentState == STATE_scanning) + { + Cashier.TimeToScan --; + if (Cashier.TimeToScan == 0) + { + Cashier.CurrentItemIndex++; + Cashier.CurrentState = STATE_ready_for_item; + printf("Time since start: %ds. Cashier %d scanned product %d. %d to go.\n", + TimePassed, Index, Cashier.CurrentItemIndex, + CUSTOMER_ITEM_COUNT-Cashier.CurrentItemIndex); + } + } + else if (Cashier.CurrentState == STATE_ready_for_customer) + { + if(NextQueueIndex < 3) + { + Cashier.CurrentCustomer = NextQueueIndex++; + Cashier.CurrentState = STATE_ready_for_item; + Cashier.CurrentItemIndex = 0; + printf("Cashier %d currently serving customer %d.\n", Index, Cashier.CurrentCustomer); + } + else + { + // NOTE: Counting up when Cashier is done and there is no more + // customer to serve + FinishedCashiers++; + + // NOTE: we added a State for when the cashier is done + Cashier.CurrentState = STATE_finished; + } + } +} + +int main() +{ + InitCustomerQueue(); + + initTimeTable(); + NextQueueIndex = 0; + + // NOTE: we now need to wait until all cashiers are done + while(FinishedCashiers < CASHIER_COUNT) + { + // TODO: loop over all cashiers + step(0); + + //--------------------------------- + + // NOTE: this gives us slightly diffrent numbers, + // because we are now also counting state changes. + // You could change that. It just would make the program more complex. + TimePassed ++; + } +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/regex b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/regex new file mode 100644 index 0000000..4ae6aeb --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/regex @@ -0,0 +1 @@ +^(.*\n)*Cashier 0(.*\n)*Cashier 1.*\n(.*\n)*.*103s.*$ \ No newline at end of file diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/supermarket.h b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/supermarket.h new file mode 100644 index 0000000..410a8bf --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/supermarket.h @@ -0,0 +1,65 @@ +typedef enum +{ + STATE_ready_for_item, + STATE_ready_for_customer, + STATE_scanning, + STATE_finished, +}state; + +typedef enum +{ + tissues, + pasta, + tomato_sauce, + bread, + butter, + batteries, + toothbrush, + + ITEM_TYPE_COUNT, +}item; + +item Time[ITEM_TYPE_COUNT]; + +void initTimeTable() +{ + Time[tissues] = 1; + Time[pasta] = 2; + Time[tomato_sauce] = 3; + Time[bread] = 10; + Time[butter] = 2; + Time[batteries] = 2; + Time[toothbrush] = 1; +} +#define CUSTOMER_ITEM_COUNT 5 +typedef struct +{ + item Items[CUSTOMER_ITEM_COUNT]; + int PackingSpeed; +}customer; + +customer CustomerQueue[3]; +void InitCustomerQueue() +{ + CustomerQueue[0].Items[0] = tissues; + CustomerQueue[0].Items[1] = pasta; + CustomerQueue[0].Items[2] = tomato_sauce; + CustomerQueue[0].Items[3] = bread; + CustomerQueue[0].Items[4] = butter; + CustomerQueue[0].PackingSpeed = 2; + + CustomerQueue[1].Items[0] = toothbrush; + CustomerQueue[1].Items[1] = batteries; + CustomerQueue[1].Items[2] = bread; + CustomerQueue[1].Items[3] = bread; + CustomerQueue[1].Items[4] = butter; + CustomerQueue[1].PackingSpeed = 3; + + CustomerQueue[2].Items[0] = bread; + CustomerQueue[2].Items[1] = batteries; + CustomerQueue[2].Items[2] = tomato_sauce; + CustomerQueue[2].Items[3] = pasta; + CustomerQueue[2].Items[4] = tissues; + CustomerQueue[2].PackingSpeed = 9; + +} diff --git a/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/type b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/07-multiple-cashiers/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-newcomers/sections/04-supermarket/section b/oer/courses/c-newcomers/sections/04-supermarket/section new file mode 100644 index 0000000..9e3a7e4 --- /dev/null +++ b/oer/courses/c-newcomers/sections/04-supermarket/section @@ -0,0 +1 @@ +{"title": "Supermarket", "description": "Simulate cashiers and customers"} diff --git a/oer/courses/c-openmp/meta b/oer/courses/c-openmp/meta new file mode 100644 index 0000000..a107d5f --- /dev/null +++ b/oer/courses/c-openmp/meta @@ -0,0 +1 @@ +{"title": "OpenMP", "description": "A quick introduction to OpenMP. A basic understanding of C is a requirment for this course."} diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/Makefile b/oer/courses/c-openmp/sections/01-introduction/00-parallel/Makefile new file mode 100644 index 0000000..8bdb4e3 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/Makefile @@ -0,0 +1,5 @@ + +all: + gcc -fopenmp -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/content.md b/oer/courses/c-openmp/sections/01-introduction/00-parallel/content.md new file mode 100644 index 0000000..51e90c9 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/content.md @@ -0,0 +1,12 @@ +OpenMP is a parallelization framework that allows the programmer to easily do thread-level parallelization. +It provides simple compiler directives, with which you mark up the parts of the code, which you want to execute in parallel. + +## Knowledge + +The simplest compiler directive is the ``#pragma omp parallel``, which opens a parallel region, where the same code is executed on all threads. +You can find all the important directives in the [quick reference](http://openmp.org/mp-documents/OpenMP3.1-CCard.pdf). +Additional details can be found in the full [OpenMP specification](http://www.openmp.org/mp-documents/OpenMP3.1.pdf). For details on OpenMP compiler directives see section 2. + +## Task + +Use the omp parallel pragma to print the thread number of multiple threads. diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/meta b/oer/courses/c-openmp/sections/01-introduction/00-parallel/meta new file mode 100644 index 0000000..210a30b --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/meta @@ -0,0 +1 @@ +{"title": "Hello World!"} diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/program b/oer/courses/c-openmp/sections/01-introduction/00-parallel/program new file mode 100755 index 0000000..bb7a1d9 Binary files /dev/null and b/oer/courses/c-openmp/sections/01-introduction/00-parallel/program differ diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/program.c b/oer/courses/c-openmp/sections/01-introduction/00-parallel/program.c new file mode 100644 index 0000000..3c6a8db --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/program.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + // To execute the code in parallel insert the omp parallel pragma below: + + printf("Hello World from thread: %d\n", omp_get_thread_num()); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/regex b/oer/courses/c-openmp/sections/01-introduction/00-parallel/regex new file mode 100644 index 0000000..76333a0 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/regex @@ -0,0 +1 @@ +(Hello World from thread: \d\n){2,} diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/solution.c b/oer/courses/c-openmp/sections/01-introduction/00-parallel/solution.c new file mode 100644 index 0000000..e1ee048 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/solution.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + // To execute the code in parallel insert the omp parallel pragma below: + #pragma omp parallel + printf("Hello World from thread: %d\n", omp_get_thread_num()); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/00-parallel/type b/oer/courses/c-openmp/sections/01-introduction/00-parallel/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/00-parallel/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/Makefile b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/Makefile new file mode 100644 index 0000000..8bdb4e3 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/Makefile @@ -0,0 +1,5 @@ + +all: + gcc -fopenmp -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/a.out b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/a.out new file mode 100755 index 0000000..6d3f33b Binary files /dev/null and b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/a.out differ diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/content.md b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/content.md new file mode 100644 index 0000000..08acc12 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/content.md @@ -0,0 +1,11 @@ +In this exercise you learn how to specify the number of threads. + +## Knowledge + +Many of the omp directives can be further specified by clauses. Among others you can specify shared variables or private ones. +With the clause ``num_threads()`` you can tell the compiler, how many threads are supposed to run the code. +To find out which clauses can be used with each directive, check the [quick reference](http://openmp.org/mp-documents/OpenMP3.1-CCard.pdf). + +## Task + +Run the code on 7 different threads. \ No newline at end of file diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/meta b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/meta new file mode 100644 index 0000000..ade798c --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/meta @@ -0,0 +1 @@ +{"title": "Thread Numbers"} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program new file mode 100755 index 0000000..76f7838 Binary files /dev/null and b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program differ diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program.c b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program.c new file mode 100644 index 0000000..e6289b7 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/program.c @@ -0,0 +1,11 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + // TODO: parallelize this in 7 threads: + #pragma omp parallel + printf("Thread: %d\n", omp_get_thread_num()); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/regex b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/regex new file mode 100644 index 0000000..c9a3078 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/regex @@ -0,0 +1 @@ +^(Thread: \d\n){7}$ diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/solution.c b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/solution.c new file mode 100644 index 0000000..eb7a2ca --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/solution.c @@ -0,0 +1,22 @@ +#include +#include +#include + +void workload() +{ + // We are simulating a workload by sleeping the thread + // This is obviously not an accurate representation + // of real computation, but it works for this example + sleep(1); +} + +int main(int argc, const char *argv[]) +{ + // TODO: parallelize this: + #pragma omp parallel num_threads(7) + #pragma omp for + for (int i = 0; i<10; i++) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + } + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-numthreads/type b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-numthreads/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/Makefile b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/Makefile new file mode 100644 index 0000000..8bdb4e3 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/Makefile @@ -0,0 +1,5 @@ + +all: + gcc -fopenmp -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/content.md b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/content.md new file mode 100644 index 0000000..54db812 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/content.md @@ -0,0 +1,12 @@ +For this exercise, we are using a simulated workload to see the effect of distributing it to different threads. + +## Knowledge +In this case we have a simple for-loop. If we would leave the code as is, each thread would just do the same work. +But we want to increase the speed by distributing the workload among the threads. +To do that, we have to tell the compiler with the directive ``#pragma omp for``, that the for loop should be split up +and each thread just does one part of the range. + +## Task + +Parrallelize the loop such that the workload is shared among all threads! +You will notice an increase in performance. The time measured time is wall-clock time, meaning the real world time that elapsed during the computation. diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/meta b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/meta new file mode 100644 index 0000000..0bf2017 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/meta @@ -0,0 +1 @@ +{"title": "For Loops"} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/program.c b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/program.c new file mode 100644 index 0000000..bce81b2 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/program.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +void workload() +{ + // We are simulating a workload by sleeping the thread + // This is obviously not an accurate representation + // of real computation, but it works for this example + usleep(100000); +} + +int main(int argc, const char *argv[]) +{ + // this sets the default number of threads to 5 + // you can still overwrite the number of threads used in a parallel region with a clause + omp_set_num_threads(5); + + // We use openMP functions to measure our programs run time. + double start = omp_get_wtime(); + + #pragma omp parallel + { + // A for loop inside a parallel section can be parallelized using + // the for directive + // TODO: Share the workload of the loop below among all threads + for (int i = 0; i<10; i++) { + workload(); + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + } + } + + double end = omp_get_wtime(); + printf("That took a total of %f seconds.\n", end - start); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/regex b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/regex new file mode 100644 index 0000000..bac3232 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/regex @@ -0,0 +1 @@ +That took a total of 0\.2.* diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/solution.c b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/solution.c new file mode 100644 index 0000000..eb7a2ca --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/solution.c @@ -0,0 +1,22 @@ +#include +#include +#include + +void workload() +{ + // We are simulating a workload by sleeping the thread + // This is obviously not an accurate representation + // of real computation, but it works for this example + sleep(1); +} + +int main(int argc, const char *argv[]) +{ + // TODO: parallelize this: + #pragma omp parallel num_threads(7) + #pragma omp for + for (int i = 0; i<10; i++) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + } + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/type b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/01-parallel-for/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/Makefile b/oer/courses/c-openmp/sections/01-introduction/05-private/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/content.md b/oer/courses/c-openmp/sections/01-introduction/05-private/content.md new file mode 100644 index 0000000..b26da5a --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/content.md @@ -0,0 +1,11 @@ +We want each of the two threads in the code below to print the numbers from 5-10. With the current code this is not working as both threads use the same counter in the while loop. +Sometimes we want each thread to have it's own copy of a variable, when this is desired we can use OpenMPs private clause to give each thread it's own instance. + +## Knowledge + +To mark a variable as private you add ``private(var1, var2)`` to your directive. Some directive such as the omp for directiv assume certain variables as private by default. +In the omp for example it is the loop counter. Thats why you didn't had to specify a private varible befor. + +## Task + +Add a private clause to the code, so that both threads output the numbers 5 to 10. diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/meta b/oer/courses/c-openmp/sections/01-introduction/05-private/meta new file mode 100644 index 0000000..6b7f3d1 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/meta @@ -0,0 +1 @@ +{"title": "Private Variables"} diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/program.c b/oer/courses/c-openmp/sections/01-introduction/05-private/program.c new file mode 100644 index 0000000..c70ff24 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/program.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + // We use two threads for this exercise + omp_set_num_threads(2); + + // The variable is declared outside the parallel section + int i; + + // The variable needs to be private to get the full output + #pragma omp parallel + { + i = 5; + while(i <= 10) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + i++; + } + } + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/regex b/oer/courses/c-openmp/sections/01-introduction/05-private/regex new file mode 100644 index 0000000..8ddb688 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/regex @@ -0,0 +1 @@ +(Iteration\s\d+\sin\sthread:\s[01]\n?){12} diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/solution.c b/oer/courses/c-openmp/sections/01-introduction/05-private/solution.c new file mode 100644 index 0000000..997a4fb --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/solution.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + // We use two threads for this exercise + omp_set_num_threads(2); + + // The variable is declared outside the parallel section + int i; + + // The variable needs to be private to get the full output + #pragma omp parallel private(i) + { + i = 5; + while(i <= 10) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + i++; + } + } + + return 0; +} diff --git a/oer/courses/c-openmp/sections/01-introduction/05-private/type b/oer/courses/c-openmp/sections/01-introduction/05-private/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/05-private/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/01-introduction/section b/oer/courses/c-openmp/sections/01-introduction/section new file mode 100644 index 0000000..19363f4 --- /dev/null +++ b/oer/courses/c-openmp/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Introduction", "description": "Basic constructs of OpenMP."} diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/Makefile b/oer/courses/c-openmp/sections/02-advanced/02-add/Makefile new file mode 100644 index 0000000..bbde708 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/content.md b/oer/courses/c-openmp/sections/02-advanced/02-add/content.md new file mode 100644 index 0000000..e71375e --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/content.md @@ -0,0 +1,13 @@ +Multiple threads writing to the same variable at the same time lead to data races, which can cause random behaviour depending on, which threads is faster, or +corrupt your data. To prevent these race conditions we need to lock all outer threads out while one is writing to a shared variable. + +## Knowledge + +One way of dealing with race conditions are critical sections. Only one thread is allowed in the same critical sections. The others have to wait until the critical section is free again. +Then the next thread can claim the critical section. You could solve this particular problem more elegantly and we will come back to that, but for now just use critical sections. + +To mark a block as a critical section, use the compiler directive ``pragma omp critical``. + +## Task + +Resolve the race condition with a critical section. diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/meta b/oer/courses/c-openmp/sections/02-advanced/02-add/meta new file mode 100644 index 0000000..59145bf --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/meta @@ -0,0 +1 @@ +{"title": "Dataraces & Critical Sections"} diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/program.c b/oer/courses/c-openmp/sections/02-advanced/02-add/program.c new file mode 100644 index 0000000..3dc0f8e --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/program.c @@ -0,0 +1,20 @@ +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + int sum = 0; + + // The line below is just shorthand for a + // loop directive inside a parallel block + #pragma omp parallel for num_threads(2) + for (int i = 0; i < 10000; i++) { + // TODO: prevent this from causing race conditions + // use a critical section + sum++; + } + + printf("sum: %d\n", sum); + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/regex b/oer/courses/c-openmp/sections/02-advanced/02-add/regex new file mode 100644 index 0000000..28b74ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/regex @@ -0,0 +1 @@ +sum: 10000 diff --git a/oer/courses/c-openmp/sections/02-advanced/02-add/type b/oer/courses/c-openmp/sections/02-advanced/02-add/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/02-add/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/Makefile b/oer/courses/c-openmp/sections/02-advanced/03-reduce/Makefile new file mode 100644 index 0000000..bbde708 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/content.md b/oer/courses/c-openmp/sections/02-advanced/03-reduce/content.md new file mode 100644 index 0000000..0369aaf --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/content.md @@ -0,0 +1,13 @@ +Some race conditions can be resolved by every thread calculating the result in a private variable and combining all the results in the end. +This is often faster, because it involves less waiting. + +## Knowledge + +To use the reduction, you have to add the reduction clause ``reduction(operator : var)`` to your compiler directive. +You can use reductions for a handful of operations. Most of the arithmetic operators and some of the logic and bitwise ones plus min and max. +For a complete list check the [quick reference](http://www.openmp.org/wp-content/uploads/OpenMP3.1-CCard.pdf). +Reduction only need to synchronize as often as there are threads instead of how many operations are actually done. + +## Task + +Instead of using a critical section as before, try your hand at a reduction variable instead. diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/meta b/oer/courses/c-openmp/sections/02-advanced/03-reduce/meta new file mode 100644 index 0000000..57e39d3 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/meta @@ -0,0 +1 @@ +{"title": "Reductions"} diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/program.c b/oer/courses/c-openmp/sections/02-advanced/03-reduce/program.c new file mode 100644 index 0000000..a763b2d --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/program.c @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + int sum = 0; + + // TODO: Use a reduction clause instead to add up the values + #pragma omp parallel for num_threads(2) + for (int i = 0; i < 10000; i++) { + sum++; + } + + printf("sum: %d\n", sum); + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/regex b/oer/courses/c-openmp/sections/02-advanced/03-reduce/regex new file mode 100644 index 0000000..28b74ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/regex @@ -0,0 +1 @@ +sum: 10000 diff --git a/oer/courses/c-openmp/sections/02-advanced/03-reduce/type b/oer/courses/c-openmp/sections/02-advanced/03-reduce/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/03-reduce/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/Makefile b/oer/courses/c-openmp/sections/02-advanced/04-atomic/Makefile new file mode 100644 index 0000000..bbde708 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=c99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/content.md b/oer/courses/c-openmp/sections/02-advanced/04-atomic/content.md new file mode 100644 index 0000000..92392ce --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/content.md @@ -0,0 +1,12 @@ +Another synchronization method are atomics. + +## Knowledge + +Atomics ensure that the marked variables are updated in one step, without any interuptions. That way no other thread can corrupt the data. +They are not as versatile as critical sections, but if you can use them, they are faster. If you are in a situation, where you can a reduction, +you should do so, because even though atomics are fast, the less synchronizations of the reductions will still save more time. + +## Task + +We use the same program as before. +Use the atomic directive to solve the race condition. diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/meta b/oer/courses/c-openmp/sections/02-advanced/04-atomic/meta new file mode 100644 index 0000000..9bf0e13 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/meta @@ -0,0 +1 @@ +{"title": "Atomic Operations"} diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/program.c b/oer/courses/c-openmp/sections/02-advanced/04-atomic/program.c new file mode 100644 index 0000000..0c4771a --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/program.c @@ -0,0 +1,17 @@ +#include +#include + +int main(int argc, const char *argv[]) +{ + int sum = 0; + // Use an atomic operation instead to add up the values + + #pragma omp parallel for num_threads(2) + for (int i = 0; i < 10000; i++) { + sum++; + } + + printf("sum: %d\n", sum); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/regex b/oer/courses/c-openmp/sections/02-advanced/04-atomic/regex new file mode 100644 index 0000000..28b74ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/regex @@ -0,0 +1 @@ +sum: 10000 diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/solution.c b/oer/courses/c-openmp/sections/02-advanced/04-atomic/solution.c new file mode 100644 index 0000000..e57faff --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/solution.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void workload() +{ + // We are simulating a workload by sleeping the thread + // This is obviously not an accurate representation + // of real computation, but it works for this example + sleep(1); +} + +int main(int argc, const char *argv[]) +{ + // TODO: parallelize this: + #pragma omp parallel for num_threads(7) + for (int i = 0; i<10; i++) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + } + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/04-atomic/type b/oer/courses/c-openmp/sections/02-advanced/04-atomic/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/04-atomic/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/Makefile b/oer/courses/c-openmp/sections/02-advanced/07-tasks/Makefile new file mode 100644 index 0000000..8bdb4e3 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/Makefile @@ -0,0 +1,5 @@ + +all: + gcc -fopenmp -lrt --std=c99 program.c -o program +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/content.md b/oer/courses/c-openmp/sections/02-advanced/07-tasks/content.md new file mode 100644 index 0000000..d32b593 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/content.md @@ -0,0 +1,10 @@ +Task offer an easy way to offload a block of code to another thread, while the main thread can keep going. + +## Knowledge + +To mark a block of code as a task, use the ``pragma omp task`` directive. The current thread will keep going, while another thread will execute the specified block. +If you need to be sure that all the task are done before you proceed use the ``pragma omp taskwait`` directive. + +## Task + +Use task to speed up the code. \ No newline at end of file diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/meta b/oer/courses/c-openmp/sections/02-advanced/07-tasks/meta new file mode 100644 index 0000000..947d54f --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/meta @@ -0,0 +1 @@ +{"title": "Tasks"} diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/program.c b/oer/courses/c-openmp/sections/02-advanced/07-tasks/program.c new file mode 100644 index 0000000..978ba28 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/program.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +void workload() +{ + printf("Thread: %d is working on the workload.\n", omp_get_thread_num()); + sleep(1); +} + +int main(int argc, const char *argv[]) +{ + double start = omp_get_wtime(); + omp_set_num_threads(5); + // For a task to be actually executed in parallel + // it needs to be inside a parallel section + #pragma omp parallel + // As we only want to create 10 tasks we use a single section + #pragma omp single + for (int i = 0; i<10; i++) { + // TODO: Use a task directive to parallelize the workload + workload(); + } + + double end = omp_get_wtime(); + printf("That took a total of %f seconds.\n", end - start); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/regex b/oer/courses/c-openmp/sections/02-advanced/07-tasks/regex new file mode 100644 index 0000000..5dd4325 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/regex @@ -0,0 +1 @@ +That took a total of 2\..* diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/solution.c b/oer/courses/c-openmp/sections/02-advanced/07-tasks/solution.c new file mode 100644 index 0000000..7c35252 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/solution.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +void workload() +{ + sleep(1); +} + +int main(int argc, const char *argv[]) +{ + double start = omp_get_wtime(); + omp_set_num_threads(5); + // For a task to be actually executed in parallel + // it needs to be inside a parallel section + #pragma omp parallel + // As we only want to create 10 tasks we use a single section + #pragma omp single + for (int i = 0; i<10; i++) { + // Use a task to parallelize the workload + #pragma omp task + workload(); + } + + double end = omp_get_wtime(); + printf("That took a total of %f seconds.\n", end - start); + + return 0; +} diff --git a/oer/courses/c-openmp/sections/02-advanced/07-tasks/type b/oer/courses/c-openmp/sections/02-advanced/07-tasks/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/07-tasks/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/02-advanced/section b/oer/courses/c-openmp/sections/02-advanced/section new file mode 100644 index 0000000..7f0c567 --- /dev/null +++ b/oer/courses/c-openmp/sections/02-advanced/section @@ -0,0 +1 @@ +{"title": "Further OpenMP Constructs", "description": "Some of the more advanced conecpts of OpenMP."} diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/Makefile b/oer/courses/c-openmp/sections/03-debugging/01-private/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/content.html b/oer/courses/c-openmp/sections/03-debugging/01-private/content.html new file mode 100644 index 0000000..d7109f7 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/content.html @@ -0,0 +1,4 @@ +

The below Code is expected to just print 42 from both threads. Execute it and see what happens.

+

Find out why the code is behaving the way it is and fix the code using an OpenMP clause.

+ +

Hint: take a look at the documentation of the private clause.

diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/meta b/oer/courses/c-openmp/sections/03-debugging/01-private/meta new file mode 100644 index 0000000..6b7f3d1 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/meta @@ -0,0 +1 @@ +{"title": "Private Variables"} diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/program.c b/oer/courses/c-openmp/sections/03-debugging/01-private/program.c new file mode 100644 index 0000000..291cdd4 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/program.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + omp_set_num_threads(2); + + int value = 42; + // Suppose we want value to be a private variable + // The code inside the parallel section should print 42 + #pragma omp parallel private(value) + { + printf("Value: %d\n", value); + } + + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/regex b/oer/courses/c-openmp/sections/03-debugging/01-private/regex new file mode 100644 index 0000000..18f504a --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/regex @@ -0,0 +1 @@ +(Value: 42\n){2,} diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/solution.c b/oer/courses/c-openmp/sections/03-debugging/01-private/solution.c new file mode 100644 index 0000000..997a4fb --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/solution.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + // We use two threads for this exercise + omp_set_num_threads(2); + + // The variable is declared outside the parallel section + int i; + + // The variable needs to be private to get the full output + #pragma omp parallel private(i) + { + i = 5; + while(i <= 10) { + printf("Iteration %d in thread: %d\n", i, omp_get_thread_num()); + i++; + } + } + + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/01-private/type b/oer/courses/c-openmp/sections/03-debugging/01-private/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/01-private/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/Makefile b/oer/courses/c-openmp/sections/03-debugging/02-race/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/content.html b/oer/courses/c-openmp/sections/03-debugging/02-race/content.html new file mode 100644 index 0000000..1528421 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/content.html @@ -0,0 +1,3 @@ +

Some mistake snuck into the code below: it should output the number 168 with each execution but instead it mostly returns numbers just below 168.

+ +

Use one of the constructs you learned about in our introduction section.

diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/meta b/oer/courses/c-openmp/sections/03-debugging/02-race/meta new file mode 100644 index 0000000..0693a77 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/meta @@ -0,0 +1 @@ +{"title": "Primes!"} diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/program.c b/oer/courses/c-openmp/sections/03-debugging/02-race/program.c new file mode 100644 index 0000000..5b982c8 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/program.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +bool is_prime(int num) { + for (int i = 2; i < num; i++) { + if (num % i == 0) { + return false; + } + } + return true; +} + +int main(int argc, const char *argv[]) +{ + int num_primes = 0; + + #pragma omp parallel for + for (int i = 2; i < 1000; i++) + { + if (is_prime(i)) + num_primes++; + } + + printf("Number of primes: %d\n", num_primes); + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/regex b/oer/courses/c-openmp/sections/03-debugging/02-race/regex new file mode 100644 index 0000000..2ab88ea --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/regex @@ -0,0 +1 @@ +Number of primes: 168 diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/solution.c b/oer/courses/c-openmp/sections/03-debugging/02-race/solution.c new file mode 100644 index 0000000..85654a2 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/solution.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +bool is_prime(int num) { + for (int i = 2; i < num; i++) { + if (num % i == 0) { + return false; + } + } + return true; +} + +int main(int argc, const char *argv[]) +{ + int num_primes = 0; + + #pragma omp parallel for + for (int i = 2; i < 1000; i++) + { + if (is_prime(i)) + #pragma omp atomic + num_primes++; + } + + printf("Number of primes: %d\n", num_primes); + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/02-race/type b/oer/courses/c-openmp/sections/03-debugging/02-race/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/02-race/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/Makefile b/oer/courses/c-openmp/sections/03-debugging/03-shared/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/content.html b/oer/courses/c-openmp/sections/03-debugging/03-shared/content.html new file mode 100644 index 0000000..ec98ccc --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/content.html @@ -0,0 +1 @@ +

We just want to print the numbers from one to five in each thread, for some reason we don't get them all. What is the reason, how can we fix this?

diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/meta b/oer/courses/c-openmp/sections/03-debugging/03-shared/meta new file mode 100644 index 0000000..e642494 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/meta @@ -0,0 +1 @@ +{"title": "For Loop"} diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/program.c b/oer/courses/c-openmp/sections/03-debugging/03-shared/program.c new file mode 100644 index 0000000..17c368a --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/program.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + int i; + #pragma omp parallel num_threads(2) + for (i = 1; i <= 5; i++) + { + printf("Number: %d\n", i); + } + + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/regex b/oer/courses/c-openmp/sections/03-debugging/03-shared/regex new file mode 100644 index 0000000..109ded8 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/regex @@ -0,0 +1 @@ +(Number:\s\d\n){10} diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/solution.c b/oer/courses/c-openmp/sections/03-debugging/03-shared/solution.c new file mode 100644 index 0000000..85654a2 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/solution.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +bool is_prime(int num) { + for (int i = 2; i < num; i++) { + if (num % i == 0) { + return false; + } + } + return true; +} + +int main(int argc, const char *argv[]) +{ + int num_primes = 0; + + #pragma omp parallel for + for (int i = 2; i < 1000; i++) + { + if (is_prime(i)) + #pragma omp atomic + num_primes++; + } + + printf("Number of primes: %d\n", num_primes); + return 0; +} diff --git a/oer/courses/c-openmp/sections/03-debugging/03-shared/type b/oer/courses/c-openmp/sections/03-debugging/03-shared/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/03-shared/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/03-debugging/section b/oer/courses/c-openmp/sections/03-debugging/section new file mode 100644 index 0000000..614a425 --- /dev/null +++ b/oer/courses/c-openmp/sections/03-debugging/section @@ -0,0 +1 @@ +{"title": "Debugging", "description": "Learn how to find and solve common mistakes."} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/Makefile b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/content.html b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/content.html new file mode 100644 index 0000000..357c6cc --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/content.html @@ -0,0 +1,2 @@ +

This program displays a representation of the Mandelbrot set.

+

Modify the code to run the calculation in parallel. You will be able to observe performance improvements.

diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/meta b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/meta new file mode 100644 index 0000000..73f850c --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/meta @@ -0,0 +1 @@ +{"title": "Mandelbrot Set"} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program new file mode 100755 index 0000000..a0f6fc4 Binary files /dev/null and b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program differ diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program.c b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program.c new file mode 100644 index 0000000..f619a64 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/program.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#define X_PIXEL 1000 +#define Y_PIXEL 1000 + +double scaled_x(int x) { + return -2.5 + (3.0 / X_PIXEL) * (double)x; +} + +double scaled_y(int y) { + return -2.0 + (4.0 / Y_PIXEL) * (double)y; +} + +int main(int argc, const char *argv[]) +{ + double start = omp_get_wtime(); + + char picture[X_PIXEL][Y_PIXEL]; + for (int px = 0; px < X_PIXEL; px++) + for (int py = 0; py < Y_PIXEL; py++) + { + double cx = scaled_x(px); + double cy = scaled_y(py); + double x = 0.0; + double y = 0.0; + int i = 0; + int max_i = 1000; + while(i < max_i && x*x + y*y < (1 << 16)) + { + double x_tmp = x*x - y*y + cx; + double y_tmp = 2*x*y + cy; + x = x_tmp; + y = y_tmp; + i++; + } + if (i == max_i) { + picture[px][py] = '*'; + } else { + picture[px][py] = ' '; + } + } + + double end = omp_get_wtime(); + + // We downscale the image + // by only printing one in twenty pixels + for (int x = 0; x < X_PIXEL; x+=20) { + printf("\n"); + for (int y = 0; y < Y_PIXEL; y+=20) + printf("%c", picture[x][y]); + + } + + printf("\nComputation took %f seconds\n", end - start); +} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/regex b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/regex new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/regex @@ -0,0 +1 @@ +.* diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/solution.c b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/solution.c new file mode 100644 index 0000000..8cad451 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/solution.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#define X_PIXEL 1000 +#define Y_PIXEL 1000 + +static inline bool in_circle(double x, double y) +{ + return (x*x + y*y < 1.0); +} + +double scaled_x(int x) { + return -2.5 + (3.0 / X_PIXEL) * (double)x; +} + +double scaled_y(int y) { + return -2.0 + (4.0 / Y_PIXEL) * (double)y; +} + +int main(int argc, const char *argv[]) +{ + double start = omp_get_wtime(); + + char picture[X_PIXEL][Y_PIXEL]; + for (int px = 0; px < X_PIXEL; px++) + for (int py = 0; py < Y_PIXEL; py++) + { + double cx = scaled_x(px); + double cy = scaled_y(py); + double x = 0.0; + double y = 0.0; + int i = 0; + int max_i = 1000; + while(i < max_i && x*x + y*y < (1 << 16)) + { + double x_tmp = x*x - y*y + cx; + double y_tmp = 2*x*y + cy; + x = x_tmp; + y = y_tmp; + i++; + } + if (i == max_i) { + picture[px][py] = '*'; + } else { + picture[px][py] = ' '; + } + } + + double end = omp_get_wtime(); + + // We downscale the image + // by only printing one in twenty pixels + for (int x = 0; x < X_PIXEL; x+=20) { + printf("\n"); + for (int y = 0; y < Y_PIXEL; y+=20) + printf("%c", picture[x][y]); + + } + + printf("\nComputation took %f seconds\n", end - start); +} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/type b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/00-mandelbrot/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/Makefile b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/Makefile new file mode 100644 index 0000000..7f6d788 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/Makefile @@ -0,0 +1,6 @@ + +all: + gcc -fopenmp -lm --std=gnu99 program.c -o program + +clean: + rm -f program diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/a.out b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/a.out new file mode 100755 index 0000000..67b8b91 Binary files /dev/null and b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/a.out differ diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/content.html b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/content.html new file mode 100644 index 0000000..9b2bba8 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/content.html @@ -0,0 +1,8 @@ +

In this problem we aim to approximate π using the Monte Carlo method.

+ +

Modify the code to run the calculation in parallel.

+

An interesting issue arises when we try to have reproducible computation. + Simply using a seeded pseudo random generator, while accessing it from multiple threads (in a different order each time) defeats the purpose as our computations are still non-deterministic. + Instead we use a different generator state in each thread + We use the erand48 function to explicitly pass the generators state in each call. +To ensure different random values for each thread they also need to be seeded with the thread number.

diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/meta b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/meta new file mode 100644 index 0000000..e868d5b --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/meta @@ -0,0 +1 @@ +{"title": "Approximating Pi"} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program new file mode 100755 index 0000000..7913d47 Binary files /dev/null and b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program differ diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program.c b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program.c new file mode 100644 index 0000000..3d7e771 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/program.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include + +static inline bool in_circle(double x, double y) +{ + return (x*x + y*y < 1.0); +} + +int main(int argc, const char *argv[]) +{ + omp_set_num_threads(10); + // A constant seed is used to keep our results reproducible + srand48(42); + + double x; + double y; + + int in_circle_count = 0; + int total_count = 0; + + unsigned short rand_state[3] = {22, 24, 90}; + double start = omp_get_wtime(); + + // We use now use the Monte Carlo method of approximating pi + // TODO: parallelize this block while avoiding data races: + { + rand_state[0] = rand_state[0] * (unsigned short)omp_get_num_threads(); + + // TODO: Use the omp for directive to paralellize + // a loop inside a parallel block + for (int i = 0; i < 90000000; i++) { + x = erand48(rand_state); + y = erand48(rand_state); + + if (in_circle(x, y)) { + in_circle_count++; + } + total_count++; + } + } + double quater_pi = (double)in_circle_count / (double)total_count; + + double end = omp_get_wtime(); + printf("Pi is: %f\n", quater_pi * 4); + printf("That took a total of %f seconds.\n", end - start); + return 0; +} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/regex b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/regex new file mode 100644 index 0000000..876e7e5 --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/regex @@ -0,0 +1 @@ +Pi is: 3.141711 diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/solution.c b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/solution.c new file mode 100644 index 0000000..1c8833f --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/solution.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include + +static inline bool in_circle(double x, double y) +{ + return (x*x + y*y < 1.0); +} + +int main(int argc, const char *argv[]) +{ + omp_set_num_threads(10); + // A constant seed is used to keep our results reproducible + srand48(42); + + double x; + double y; + + int in_circle_count = 0; + int total_count = 0; + + unsigned short rand_state[3]; + double start = omp_get_wtime(); + + // We use now use the Monte Carlo method of approximating pi + // TODO: parallelize this while avoiding data races: + #pragma omp parallel private(x, y, rand_state) reduction(+:total_count, in_circle_count) + { + rand_state[0] = rand_state[0] * (unsigned short)omp_get_num_threads(); + + #pragma omp for + for (int i = 0; i < 90000000; i++) { + x = erand48(rand_state); + y = erand48(rand_state); + + if (in_circle(x, y)) { + in_circle_count++; + } + total_count++; + } + } + double quater_pi = (double)in_circle_count / (double)total_count; + + double end = omp_get_wtime(); + printf("Pi is: %f\n", quater_pi * 4); + printf("That took a total of %f seconds.\n", end - start); + return 0; +} diff --git a/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/type b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/01-montecarlo/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/c-openmp/sections/04-problem-solving/section b/oer/courses/c-openmp/sections/04-problem-solving/section new file mode 100644 index 0000000..f6b0d8d --- /dev/null +++ b/oer/courses/c-openmp/sections/04-problem-solving/section @@ -0,0 +1 @@ +{"title": "Problem Solving", "description": "Apply what you learned to new problems."} diff --git a/oer/courses/example-course/meta b/oer/courses/example-course/meta new file mode 100644 index 0000000..f78dd4d --- /dev/null +++ b/oer/courses/example-course/meta @@ -0,0 +1 @@ +{"title": "Example Course", "description": "A dummy course to showcase the different exercise formats and features of the platform."} diff --git a/oer/courses/example-course/sections/01-introduction/00-weclome/content.html b/oer/courses/example-course/sections/01-introduction/00-weclome/content.html new file mode 100644 index 0000000..a7fb08a --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/00-weclome/content.html @@ -0,0 +1,6 @@ +

+Welcome to the introductory course for learning the C programming language. +The tutorials and problem sets presented to you are just to get you started, +for more fundamental C knowledge consider investing into a good book, +consult the documentation or browse the web. +

diff --git a/oer/courses/example-course/sections/01-introduction/00-weclome/meta b/oer/courses/example-course/sections/01-introduction/00-weclome/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/00-weclome/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/example-course/sections/01-introduction/00-weclome/type b/oer/courses/example-course/sections/01-introduction/00-weclome/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/00-weclome/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/Makefile b/oer/courses/example-course/sections/01-introduction/01-c-hello/Makefile new file mode 100644 index 0000000..82883ac --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/Makefile @@ -0,0 +1,8 @@ + +all: + gcc program.c -o program + #gcc solution.c -o solution + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/content.html b/oer/courses/example-course/sections/01-introduction/01-c-hello/content.html new file mode 100644 index 0000000..3763da3 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/content.html @@ -0,0 +1,2 @@ +

Change the following program to print "Hello World!" using the printf() function. You can always try your current +program by pressing the [Execute]-button. Once you think you have mastered the assignment you submit your solution for automatic grading.

diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/meta b/oer/courses/example-course/sections/01-introduction/01-c-hello/meta new file mode 100644 index 0000000..210a30b --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/meta @@ -0,0 +1 @@ +{"title": "Hello World!"} diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/program.c b/oer/courses/example-course/sections/01-introduction/01-c-hello/program.c new file mode 100644 index 0000000..1e161b8 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/program.c @@ -0,0 +1,8 @@ +#include + +int main(int argc, const char *argv[]) +{ + // TODO: use printf() to print "Hello World!" on the display. + printf("Hello world!"); + return 0; +} diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/regex b/oer/courses/example-course/sections/01-introduction/01-c-hello/regex new file mode 100644 index 0000000..04bd136 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/regex @@ -0,0 +1 @@ +^Hello world!$ diff --git a/oer/courses/example-course/sections/01-introduction/01-c-hello/type b/oer/courses/example-course/sections/01-introduction/01-c-hello/type new file mode 100644 index 0000000..7d393ec --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/01-c-hello/type @@ -0,0 +1 @@ +program/match-regex diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/Makefile b/oer/courses/example-course/sections/01-introduction/02-c-add/Makefile new file mode 100644 index 0000000..996955c --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/Makefile @@ -0,0 +1,13 @@ +all: + gcc program.c -o program + gcc solution.c -o solution + +test: + ./test.sh + +execute: + ./execute.sh + +clean: + rm -f program + rm -f solution diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/content.html b/oer/courses/example-course/sections/01-introduction/02-c-add/content.html new file mode 100644 index 0000000..03ce301 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/content.html @@ -0,0 +1 @@ +

Functions are helpful to organize code into easier to reuse snippets of code. Change the following progrom to return the sum of a and b. The section that requires to be changed is marked with "TODO".

diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/execute.sh b/oer/courses/example-course/sections/01-introduction/02-c-add/execute.sh new file mode 100755 index 0000000..2daecdb --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/execute.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +for (( i = 0; i < 1; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % 9 ) + 1)) + + ./program $a $b +done diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/meta b/oer/courses/example-course/sections/01-introduction/02-c-add/meta new file mode 100644 index 0000000..eacef63 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/meta @@ -0,0 +1 @@ +{"title": "A simple adder"} diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/program.c b/oer/courses/example-course/sections/01-introduction/02-c-add/program.c new file mode 100644 index 0000000..9f9e9c1 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/program.c @@ -0,0 +1,20 @@ +#include +#include + +int add(int a, int b) { + //TODO: change so that the sum of a and b is returned + return 0; +} + + +int main(int argc, const char *argv[]) +{ + int a, b, result; + + a = atoi(argv[1]); + b = atoi(argv[2]); + result = add(a, b); + + printf("The sum of a=%d and b=%d is %d\n", a, b, result); + return 0; +} diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/solution.c b/oer/courses/example-course/sections/01-introduction/02-c-add/solution.c new file mode 100644 index 0000000..4266c35 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/solution.c @@ -0,0 +1,20 @@ +#include +#include + +int add(int a, int b) { + //TODO: change so that the sum of a and b is returned + return a + b; +} + + +int main(int argc, const char *argv[]) +{ + int a, b, result; + + a = atoi(argv[1]); + b = atoi(argv[2]); + result = add(a, b); + + printf("The sum of a=%d and b=%d is %d\n", a, b, result); + return 0; +} diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/test.sh b/oer/courses/example-course/sections/01-introduction/02-c-add/test.sh new file mode 100755 index 0000000..32e81fd --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/test.sh @@ -0,0 +1,30 @@ +#!/bin/bash + + +correct=true + +for (( i = 0; i < 3; i++ )); do + a=$(( ( RANDOM % 9 ) + 1)) + b=$(( ( RANDOM % 9 ) + 1)) + + program_out=$(./program $a $b) + solution_out=$(./solution $a $b) + + if [ "$program_out" == "$solution_out" ] + then + echo "PASS " $program_out " equals " $solution_out + else + echo "FAIL " $program_out " DOES NOT EQUAL " $solution_out + correct=false + fi +done + + + +if [ "$correct" = true ] +then + echo "PASS"; +else + echo "FAIL"; +fi + diff --git a/oer/courses/example-course/sections/01-introduction/02-c-add/type b/oer/courses/example-course/sections/01-introduction/02-c-add/type new file mode 100644 index 0000000..1bb833c --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/02-c-add/type @@ -0,0 +1 @@ +program/scriptgrade diff --git a/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/.choices.swp b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/.choices.swp new file mode 100644 index 0000000..9e8236e Binary files /dev/null and b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/.choices.swp differ diff --git a/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/choices b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/choices new file mode 100644 index 0000000..eca2a9d --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/choices @@ -0,0 +1,5 @@ +Homer Simpson and Ned Flanders +*John Bardeen, Walter Brattein and William Schockley +Donald Duck, Goofy and Mickey Mouse +Tony Stark (also the inventor of IronMan) +Jules Verne diff --git a/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/meta b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/meta new file mode 100644 index 0000000..ed06a67 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/meta @@ -0,0 +1 @@ +{"title": "Quiz", "choose": "one"} diff --git a/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/question b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/question new file mode 100644 index 0000000..e1f32bb --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/question @@ -0,0 +1 @@ +Who invented the transistor? diff --git a/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/type b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/03-quiz-choose-one/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/choices b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/choices new file mode 100644 index 0000000..a309b04 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/choices @@ -0,0 +1,10 @@ +*John Bardeen ;) +*Walter Brattein ;) +*William Schockley ;) +Homer Simpson +Ned Flanders +Donald Duck +Goofy +Mickey Mouse +Tony Stark +Jules Verne diff --git a/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/meta b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/meta new file mode 100644 index 0000000..15941da --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/meta @@ -0,0 +1 @@ +{"title": "Quiz", "choose": "many"} diff --git a/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/question b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/question new file mode 100644 index 0000000..e1f32bb --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/question @@ -0,0 +1 @@ +Who invented the transistor? diff --git a/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/type b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/04-quiz-check-multiple/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/meta b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/meta new file mode 100644 index 0000000..15941da --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/meta @@ -0,0 +1 @@ +{"title": "Quiz", "choose": "many"} diff --git a/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/question b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/question new file mode 100644 index 0000000..1d80eb6 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/question @@ -0,0 +1 @@ +In which year was the transistor invented? diff --git a/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/regex b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/regex new file mode 100644 index 0000000..34ce58d --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/regex @@ -0,0 +1 @@ +1947 diff --git a/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/type b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/type new file mode 100644 index 0000000..38cbf47 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/05-quiz-insert-text/type @@ -0,0 +1 @@ +input/text diff --git a/oer/courses/example-course/sections/01-introduction/section b/oer/courses/example-course/sections/01-introduction/section new file mode 100644 index 0000000..bab5de8 --- /dev/null +++ b/oer/courses/example-course/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Introduction", "description": "The very basics."} diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/Makefile b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/Makefile new file mode 100644 index 0000000..d239e82 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/Makefile @@ -0,0 +1,7 @@ + +all: + mpicc program.c -o program + +clean: + rm -f program + rm -f job.out job.err diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/content.html b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/content.html new file mode 100644 index 0000000..3763da3 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/content.html @@ -0,0 +1,2 @@ +

Change the following program to print "Hello World!" using the printf() function. You can always try your current +program by pressing the [Execute]-button. Once you think you have mastered the assignment you submit your solution for automatic grading.

diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/job.slurm b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/job.slurm new file mode 100644 index 0000000..8c8b7b4 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/job.slurm @@ -0,0 +1,12 @@ +#!/bin/sh + +# Time limit is one minute. +# See "man sbatch" for other time formats. +#SBATCH --time=1 +# Run 10 tasks on 2 nodes. +#SBATCH -N 2 -n 10 +# Output goes to job.out, error messages to job.err. +#SBATCH --error=job.err --output=job.out + +mpiexec ./program +echo $? >> job.exit diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/meta b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/meta new file mode 100644 index 0000000..00c4b1f --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/meta @@ -0,0 +1 @@ +{"title": "Hello MPI!"} diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program new file mode 100755 index 0000000..8ea9de8 Binary files /dev/null and b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program differ diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program.c b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program.c new file mode 100644 index 0000000..af297b9 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/program.c @@ -0,0 +1,29 @@ +#include +#include + +int main(int argc, char** argv) { + // Initialize the MPI environment + MPI_Init(NULL, NULL); + + // Get the number of processes + int world_size; + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + // Get the rank of the process + int world_rank; + MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + + // Get the name of the processor + char processor_name[MPI_MAX_PROCESSOR_NAME]; + int name_len; + MPI_Get_processor_name(processor_name, &name_len); + + // Print off a hello world message + printf("Hello world from processor %s, rank %d" + " out of %d processors\n", + processor_name, world_rank, world_size); + + // Finalize the MPI environment. + MPI_Finalize(); +} + diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/regex b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/regex new file mode 100644 index 0000000..04bd136 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/regex @@ -0,0 +1 @@ +^Hello world!$ diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/type b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/type new file mode 100644 index 0000000..1960383 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/01-parallel-hello/type @@ -0,0 +1 @@ +program/match-regex-parallel diff --git a/oer/courses/example-course/sections/02-parallel-and-multifile/section b/oer/courses/example-course/sections/02-parallel-and-multifile/section new file mode 100644 index 0000000..0ba8315 --- /dev/null +++ b/oer/courses/example-course/sections/02-parallel-and-multifile/section @@ -0,0 +1 @@ +{"title": "Parallel and Multifile", "description": ""} diff --git a/oer/courses/tutorial/meta b/oer/courses/tutorial/meta new file mode 100644 index 0000000..6eeaabe --- /dev/null +++ b/oer/courses/tutorial/meta @@ -0,0 +1 @@ +{"title": "C-Tutorial", "description": "A set of questions to further strenghten your knowledge."} diff --git a/oer/courses/tutorial/sections/01-introduction/00-weclome/content.html b/oer/courses/tutorial/sections/01-introduction/00-weclome/content.html new file mode 100644 index 0000000..869e46e --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/00-weclome/content.html @@ -0,0 +1,7 @@ +

+ Welcome to the c-tutorial. This is entirely based on the german tutorial "Tutorien zur Informatik" by Dion Timmermann and Christian H. Kautz for the Hamburg Open Online University (HOOU). + This tutorial will provide questions to further strengthen your knowledge of the C-Programming-Language. The original document also provides questions for C++ and Java, but we will concentrate on c. +

+

+ It is probably a good idea to use this as complementary material for other learning sources such as our c-basic course or c-newcomers course. +

diff --git a/oer/courses/tutorial/sections/01-introduction/00-weclome/meta b/oer/courses/tutorial/sections/01-introduction/00-weclome/meta new file mode 100644 index 0000000..b75c1c1 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/00-weclome/meta @@ -0,0 +1 @@ +{"title": "Introduction"} diff --git a/oer/courses/tutorial/sections/01-introduction/00-weclome/type b/oer/courses/tutorial/sections/01-introduction/00-weclome/type new file mode 100644 index 0000000..be49eeb --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/00-weclome/type @@ -0,0 +1 @@ +text/html diff --git a/oer/courses/tutorial/sections/01-introduction/01-variables/choices b/oer/courses/tutorial/sections/01-introduction/01-variables/choices new file mode 100644 index 0000000..9bfb230 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/01-variables/choices @@ -0,0 +1,4 @@ +*A placeholder, which either stands for a single value or a range of values. +A placeholder for a single value. +A name for a constant number, like e for 2.718... +A name for a location, where you can store values to. \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/01-variables/meta b/oer/courses/tutorial/sections/01-introduction/01-variables/meta new file mode 100644 index 0000000..1ff61cd --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/01-variables/meta @@ -0,0 +1 @@ +{"title": "Variables in maths", "choose": "one"} diff --git a/oer/courses/tutorial/sections/01-introduction/01-variables/question b/oer/courses/tutorial/sections/01-introduction/01-variables/question new file mode 100644 index 0000000..9f9b86a --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/01-variables/question @@ -0,0 +1 @@ +What is a variable in maths? \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/01-variables/type b/oer/courses/tutorial/sections/01-introduction/01-variables/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/01-variables/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/tutorial/sections/01-introduction/02-variables-programming/choices b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/choices new file mode 100644 index 0000000..0950f91 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/choices @@ -0,0 +1,5 @@ +A placeholder, which either stands for a single value or a range of values. +A placeholder for a single value. +A name for a constant number, like e for 2.718... +*A name for a location, where you can store values to. +A random number. \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/02-variables-programming/meta b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/meta new file mode 100644 index 0000000..ffa53b6 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/meta @@ -0,0 +1 @@ +{"title": "Variables in programming", "choose": "one"} diff --git a/oer/courses/tutorial/sections/01-introduction/02-variables-programming/question b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/question new file mode 100644 index 0000000..c8e2eea --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/question @@ -0,0 +1 @@ +What is a variable in programming? \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/02-variables-programming/type b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/02-variables-programming/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/tutorial/sections/01-introduction/03-output/content.md b/oer/courses/tutorial/sections/01-introduction/03-output/content.md new file mode 100644 index 0000000..1e04f3b --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/03-output/content.md @@ -0,0 +1,10 @@ +Read this source code carefully. + + int var; + + var = 5; + var = 7; + + printf("%i", var); + printf("%i", var); + printf("%i", var); diff --git a/oer/courses/tutorial/sections/01-introduction/03-output/meta b/oer/courses/tutorial/sections/01-introduction/03-output/meta new file mode 100644 index 0000000..7e47604 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/03-output/meta @@ -0,0 +1 @@ +{"title": "Source Code"} diff --git a/oer/courses/tutorial/sections/01-introduction/03-output/question b/oer/courses/tutorial/sections/01-introduction/03-output/question new file mode 100644 index 0000000..b8afe91 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/03-output/question @@ -0,0 +1 @@ +What does this source code print to the console? diff --git a/oer/courses/tutorial/sections/01-introduction/03-output/regex b/oer/courses/tutorial/sections/01-introduction/03-output/regex new file mode 100644 index 0000000..6713fc2 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/03-output/regex @@ -0,0 +1 @@ +^777$ diff --git a/oer/courses/tutorial/sections/01-introduction/03-output/type b/oer/courses/tutorial/sections/01-introduction/03-output/type new file mode 100644 index 0000000..38cbf47 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/03-output/type @@ -0,0 +1 @@ +input/text diff --git a/oer/courses/tutorial/sections/01-introduction/04-value/choices b/oer/courses/tutorial/sections/01-introduction/04-value/choices new file mode 100644 index 0000000..f40f38c --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/04-value/choices @@ -0,0 +1,3 @@ +5. +*7. +5 and 7 at the same time. \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/04-value/content.md b/oer/courses/tutorial/sections/01-introduction/04-value/content.md new file mode 100644 index 0000000..51eb004 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/04-value/content.md @@ -0,0 +1,9 @@ + + int var; + + var = 5; + var = 7; + + printf("%i", var); + printf("%i", var); + printf("%i", var); diff --git a/oer/courses/tutorial/sections/01-introduction/04-value/meta b/oer/courses/tutorial/sections/01-introduction/04-value/meta new file mode 100644 index 0000000..a85db78 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/04-value/meta @@ -0,0 +1 @@ +{"title": "Value", "choose": "one"} diff --git a/oer/courses/tutorial/sections/01-introduction/04-value/question b/oer/courses/tutorial/sections/01-introduction/04-value/question new file mode 100644 index 0000000..08d0fec --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/04-value/question @@ -0,0 +1 @@ +What value does var hold after executing line 3 and think about why? \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/04-value/type b/oer/courses/tutorial/sections/01-introduction/04-value/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/04-value/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/tutorial/sections/01-introduction/05-value2/choices b/oer/courses/tutorial/sections/01-introduction/05-value2/choices new file mode 100644 index 0000000..9dcf9f6 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/05-value2/choices @@ -0,0 +1,3 @@ +5, because printf writes the latest value to the console and removes it from the variable. +*7, because printf only writes the value to the console. +5 and 7, because printf doesn't change the variable. \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/05-value2/content.md b/oer/courses/tutorial/sections/01-introduction/05-value2/content.md new file mode 100644 index 0000000..51eb004 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/05-value2/content.md @@ -0,0 +1,9 @@ + + int var; + + var = 5; + var = 7; + + printf("%i", var); + printf("%i", var); + printf("%i", var); diff --git a/oer/courses/tutorial/sections/01-introduction/05-value2/meta b/oer/courses/tutorial/sections/01-introduction/05-value2/meta new file mode 100644 index 0000000..6af714a --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/05-value2/meta @@ -0,0 +1 @@ +{"title": "Value after printf", "choose": "one"} diff --git a/oer/courses/tutorial/sections/01-introduction/05-value2/question b/oer/courses/tutorial/sections/01-introduction/05-value2/question new file mode 100644 index 0000000..1c4916b --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/05-value2/question @@ -0,0 +1 @@ +What value does var hold after executing line 5 and think about why? \ No newline at end of file diff --git a/oer/courses/tutorial/sections/01-introduction/05-value2/type b/oer/courses/tutorial/sections/01-introduction/05-value2/type new file mode 100644 index 0000000..b1552d4 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/05-value2/type @@ -0,0 +1 @@ +choice/multiple diff --git a/oer/courses/tutorial/sections/01-introduction/06-positiv/content.md b/oer/courses/tutorial/sections/01-introduction/06-positiv/content.md new file mode 100644 index 0000000..c7b68f5 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/06-positiv/content.md @@ -0,0 +1,12 @@ +Read this source code carefully. + + int var = -5; + if (var > 0){ + printf("Variable is positiv."); + } + + var = 10; + printf("Program ended."); + if (var > 0) { + printf("Variable is positiv."); + } diff --git a/oer/courses/tutorial/sections/01-introduction/06-positiv/meta b/oer/courses/tutorial/sections/01-introduction/06-positiv/meta new file mode 100644 index 0000000..74c809f --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/06-positiv/meta @@ -0,0 +1 @@ +{"title": "Is Positive?"} diff --git a/oer/courses/tutorial/sections/01-introduction/06-positiv/question b/oer/courses/tutorial/sections/01-introduction/06-positiv/question new file mode 100644 index 0000000..b8afe91 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/06-positiv/question @@ -0,0 +1 @@ +What does this source code print to the console? diff --git a/oer/courses/tutorial/sections/01-introduction/06-positiv/regex b/oer/courses/tutorial/sections/01-introduction/06-positiv/regex new file mode 100644 index 0000000..9a82f83 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/06-positiv/regex @@ -0,0 +1 @@ +^Program ended.\s*Variable is positiv.$ diff --git a/oer/courses/tutorial/sections/01-introduction/06-positiv/type b/oer/courses/tutorial/sections/01-introduction/06-positiv/type new file mode 100644 index 0000000..38cbf47 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/06-positiv/type @@ -0,0 +1 @@ +input/text diff --git a/oer/courses/tutorial/sections/01-introduction/section b/oer/courses/tutorial/sections/01-introduction/section new file mode 100644 index 0000000..f3717e4 --- /dev/null +++ b/oer/courses/tutorial/sections/01-introduction/section @@ -0,0 +1 @@ +{"title": "Variable and Output", "description": "Revision on the topic variables and output."} diff --git a/oer/exercise-formats/choice/multiple/ExerciseHandler.py b/oer/exercise-formats/choice/multiple/ExerciseHandler.py new file mode 100644 index 0000000..7f2e216 --- /dev/null +++ b/oer/exercise-formats/choice/multiple/ExerciseHandler.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json +import re +import crypt + + +print("Handler choice/multiple loaded!") + + +# helper + +# analog to value of html input field (checkbox/radio) it feels kinda odd to +# use this, maybe settle with another hash function than the default this only +# requires performance not cryptographic security +def hash(arg): + return crypt.crypt(str(arg)) + +def parse_choice(raw_choice): + choice = {"text": "", "is": "incorrect", "value": ""} + + result = re.findall(r"^([*!]?)(.*)$", raw_choice, re.DOTALL) + + value = hash(result[0][1]) + + if result[0][0] == '*': + choice = {"text": result[0][1], "is": "correct", "value": value} + elif result[0][0] == '!': + choice = {"text": result[0][1], "is": "required", "value": value} + else: + choice = {"text": result[0][1], "is": "incorrect", "value": value} + + return choice + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'choices': [''], 'question': ''} + print("ExerciseHandler choice/multiple") + print("parser.path", parser.path) + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['question'] = self.parser.get_file_content('question') + + # import and sanitize choices + data['choices'] = self.parser.get_file_content('choices').split('\n') + for i,choice in enumerate(data['choices']): + data['choices'][i] = parse_choice(choice) + + # determine how to render choices + data['input_type'] = "checkbox" + if 'choose' in parser.meta: + if parser.meta['choose'] == "one": + data['input_type'] = "radio" + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/choice/multiple/controller.py b/oer/exercise-formats/choice/multiple/controller.py new file mode 100644 index 0000000..9618885 --- /dev/null +++ b/oer/exercise-formats/choice/multiple/controller.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import re + + +def grade(ctx): + grade = 'FAIL' + + # counter + correct = 0 + correct_chosen = [] + min_correct = -1 + + incorrect = 0 + incorrect_chosen = [] + max_incorrect = 0 + + choices = ctx.data['data']['choices'] + solution = ctx.data['solution'] + + print(choices, file=sys.stderr) + print(solution, file=sys.stderr) + + if ctx.data['data']['input_type'] in ['radio']: + # choose one + # a correct selection is found? => return 'PASS' + # a incorrect selection is found? => return 'FAIL' + for choice in choices: + print(choice['value'], file=sys.stderr) + print(solution, file=sys.stderr) + + if choice['is'] in ['correct', 'required']: + if choice['value'] in solution: + correct_chosen.append(choice['value']) + grade = 'PASS' + break + else: + if choice['value'] in solution: + incorrect_chosen.append(choice['value']) + grade = 'FAIL' + break + else: + # choose many/multiple + #for choice in ctx.data['choices']: + for choice in choices: + print(choice['value'], file=sys.stderr) + print(solution, file=sys.stderr) + + if choice['is'] in ['correct', 'required']: + correct += 1 + if choice['value'] in solution: + correct_chosen.append(choice['value']) + else: + incorrect += 1 + if choice['value'] in solution: + incorrect_chosen.append(choice['value']) + + if min_correct == -1: + min_correct = correct + + print({ + 'correct': correct, + 'correct_chosen': correct_chosen, + 'min_correct': min_correct, + 'incorrect': incorrect, + 'incorrect_chosen': incorrect_chosen, + 'max_incorrect': max_incorrect, + }, file=sys.stderr) + + ctx.response_data['correct'] = correct_chosen + ctx.response_data['incorrect'] = incorrect_chosen + + if len(incorrect_chosen) > max_incorrect: + return 'FAIL' + + elif len(correct_chosen) < min_correct: + return 'FAIL' + + if len(correct_chosen) == correct: + return 'PASS' + + # grading + # max_incorrect + # min_correct + + ctx.response_data['correct'] = correct_chosen + ctx.response_data['incorrect'] = incorrect_chosen + + return grade diff --git a/oer/exercise-formats/choice/multiple/script.js b/oer/exercise-formats/choice/multiple/script.js new file mode 100644 index 0000000..8ac0444 --- /dev/null +++ b/oer/exercise-formats/choice/multiple/script.js @@ -0,0 +1,152 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + if ( output != false ) { + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + solution = {} + solution.gather = function () { + console.log("Gather solution!"); + + sol = Array(); + + $("#exercise-choices input:checked").each(function () { + console.log($(this).attr("value")); + sol.push($(this).attr("value")); + + }); + + return sol; + } + + + + job = {} + job.submit = function (action) { + + sol = solution.gather() + + submission = {"solution": sol, "slide": window.data.slide, "action": "quiz"}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + + // really timeout? + // how about handling this directly? + setTimeout(function(){ job.status(action, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type); + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + + }); + + }; + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + /** + * Extend clickable area for checkboxes and radio buttons to the parent. + * Optional: Add background coloring + */ + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-userchoice"); + + + }); + + +}); + diff --git a/oer/exercise-formats/choice/multiple/template.html b/oer/exercise-formats/choice/multiple/template.html new file mode 100644 index 0000000..ead44a3 --- /dev/null +++ b/oer/exercise-formats/choice/multiple/template.html @@ -0,0 +1,94 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + +{% block exercise_head %} + +{% endblock %} + +{% block exercise_content %} +{{ slide.content |safe }} + +
+

{{ slide_data.question }}

+ +
+ +{% for choice in slide_data.choices|shuffle %}{{ choice.text|safe }} +{% endfor %} +
+ + + + + + + + +
+{% endblock %} + + + + + + + +{% block exercise_response %} + +{% endblock %} + diff --git a/oer/exercise-formats/input/math/ExerciseHandler.py b/oer/exercise-formats/input/math/ExerciseHandler.py new file mode 100644 index 0000000..a0948be --- /dev/null +++ b/oer/exercise-formats/input/math/ExerciseHandler.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +print("Handler text/match-regex loaded!") + + +class ExerciseHandler(object): + def __init__(self): + print("ExerciseHandler text/match-regex") diff --git a/oer/exercise-formats/input/text/ExerciseHandler.py b/oer/exercise-formats/input/text/ExerciseHandler.py new file mode 100644 index 0000000..d51ce40 --- /dev/null +++ b/oer/exercise-formats/input/text/ExerciseHandler.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/match-regex loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['question'] = self.parser.get_file_content('question') + data['regex'] = self.parser.get_file_content('regex').strip() + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/input/text/controller.py b/oer/exercise-formats/input/text/controller.py new file mode 100644 index 0000000..4051c88 --- /dev/null +++ b/oer/exercise-formats/input/text/controller.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# program/match-regex + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import subprocess +import re + + + + +def grade(ctx): + """A function that governs the grading process when different from default. + Expected is return value that indicates if the task passed or failed.""" + + print(ctx.data['data']['regex'], file=sys.stderr) + print(ctx.data['solution'], file=sys.stderr) + + if re.match(ctx.data['data']['regex'], ctx.data['solution') != None: + return 'PASS' + else: + return 'FAIL' + + + + +def response(ctx): + + grade = ctx.grade_result + msg = "" + return {'output': output, 'grade': grade, 'msg': msg, 'data': None} diff --git a/oer/exercise-formats/input/text/script.js b/oer/exercise-formats/input/text/script.js new file mode 100644 index 0000000..15fcd55 --- /dev/null +++ b/oer/exercise-formats/input/text/script.js @@ -0,0 +1,138 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (action) { + + console.log("Test submission issued.."); + console.log( $("#solution").val() ); + + submission = {"solution": $("#solution").val(), "action": "quiz", "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + setTimeout(function(){ job.status(action, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type) + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/input/text/styles.css b/oer/exercise-formats/input/text/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/oer/exercise-formats/input/text/template.html b/oer/exercise-formats/input/text/template.html new file mode 100644 index 0000000..d40596e --- /dev/null +++ b/oer/exercise-formats/input/text/template.html @@ -0,0 +1,68 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_head %} + +{% endblock %} + + +{% block exercise_content %} +{{ slide.content |safe }} + +
+ +

{{ slide_data.question }}

+ +
+ + +
+ +
+{% endblock %} + + +{% block exercise_response %} + +{% endblock %} + diff --git a/oer/exercise-formats/program/Session.vim b/oer/exercise-formats/program/Session.vim new file mode 100644 index 0000000..193cd1c --- /dev/null +++ b/oer/exercise-formats/program/Session.vim @@ -0,0 +1,541 @@ +let SessionLoad = 1 +if &cp | set nocp | endif +let s:cpo_save=&cpo +set cpo&vim +nmap gx NetrwBrowseX +nnoremap NetrwBrowseX :call netrw#NetrwBrowseX(expand(""),0) +let &cpo=s:cpo_save +unlet s:cpo_save +set autoindent +set backspace=indent,eol,start +set copyindent +set expandtab +set fileencodings=ucs-bom,utf-8,default,latin1 +set helplang=en +set laststatus=2 +set mouse=a +set printoptions=paper:a4 +set ruler +set runtimepath=~/.vim,/var/lib/vim/addons,/usr/share/vim/vimfiles,/usr/share/vim/vim74,/usr/share/vim/vimfiles/after,/var/lib/vim/addons/after,~/.vim/after +set shiftround +set shiftwidth=4 +set smarttab +set softtabstop=4 +set suffixes=.bak,~,.swp,.o,.info,.aux,.log,.dvi,.bbl,.blg,.brf,.cb,.ind,.idx,.ilg,.inx,.out,.toc +set tabstop=4 +set wildmenu +set wildmode=list:longest,full +let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 +let v:this_session=expand(":p") +silent only +cd ~/git/HOOU/oer/exercise-formats/program +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +set shortmess=aoO +badd +0 match-regex-parallel/controller.py +badd +0 match-regex-parallel/ExerciseHandler.py +badd +0 ../../../django-platform/runner/tasks.py +badd +0 match-regex-parallel/script.js +argglobal +silent! argdel * +set stal=2 +edit match-regex-parallel/controller.py +set splitbelow splitright +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +argglobal +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +set colorcolumn=80 +setlocal colorcolumn=80 +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal copyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'python' +setlocal filetype=python +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispwords= +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal modeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=4 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'python' +setlocal syntax=python +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal noundofile +setlocal undolevels=-123456 +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 46 - ((6 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +46 +normal! 0 +tabedit match-regex-parallel/script.js +set splitbelow splitright +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +argglobal +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +set colorcolumn=80 +setlocal colorcolumn=80 +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal copyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'javascript' +setlocal filetype=javascript +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispwords= +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal modeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=4 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'javascript' +setlocal syntax=javascript +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal noundofile +setlocal undolevels=-123456 +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 107 - ((52 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +107 +normal! 020| +tabedit match-regex-parallel/ExerciseHandler.py +set splitbelow splitright +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +argglobal +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +set colorcolumn=80 +setlocal colorcolumn=80 +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal copyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'python' +setlocal filetype=python +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispwords= +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal modeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=4 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'python' +setlocal syntax=python +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal noundofile +setlocal undolevels=-123456 +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 32 - ((31 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +32 +normal! 041| +tabedit ../../../django-platform/runner/tasks.py +set splitbelow splitright +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +argglobal +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +set colorcolumn=80 +setlocal colorcolumn=80 +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal copyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'python' +setlocal filetype=python +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispwords= +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal modeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=4 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'python' +setlocal syntax=python +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal noundofile +setlocal undolevels=-123456 +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 1 - ((0 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +1 +normal! 0 +tabnext 2 +set stal=1 +if exists('s:wipebuf') + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 shortmess=filnxtToO +let s:sx = expand(":p:r")."x.vim" +if file_readable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/oer/exercise-formats/program/match-regex-multifile/ExerciseHandler.py b/oer/exercise-formats/program/match-regex-multifile/ExerciseHandler.py new file mode 100644 index 0000000..782867e --- /dev/null +++ b/oer/exercise-formats/program/match-regex-multifile/ExerciseHandler.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/match-regex loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['code'] = self.parser.get_file_content('program.c') + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/program/match-regex-multifile/controller.py b/oer/exercise-formats/program/match-regex-multifile/controller.py new file mode 100644 index 0000000..0e8d59f --- /dev/null +++ b/oer/exercise-formats/program/match-regex-multifile/controller.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +# program/match-regex + + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import subprocess + + + +def build(context): + pass + +def run(context): + pass + + +# The following code serves to illustrate what will be generated automaticly +# for simple programming tasks in C. +# AUTO-GENERATED CODE: +def grade(context): + """A function that governs the grading process when different from default. + Expected is return value that indicates if the task passed or failed.""" + print("default GRADE HANDLER says hello ;) context ist: %s" % context, file=sys.stderr) + return "hoho ;)" + + diff --git a/oer/exercise-formats/program/match-regex-multifile/script.js b/oer/exercise-formats/program/match-regex-multifile/script.js new file mode 100644 index 0000000..bd802ac --- /dev/null +++ b/oer/exercise-formats/program/match-regex-multifile/script.js @@ -0,0 +1,138 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (type) { + + console.log("Test submission issued.."); + console.log( $("#c-code").val() ); + + submission = {"solution": cEditor.getValue(), "cmd": "run.sh", "type": type, "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + setTimeout(function(){ job.status(type, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type) + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/program/match-regex-multifile/styles.css b/oer/exercise-formats/program/match-regex-multifile/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/oer/exercise-formats/program/match-regex-multifile/template.html b/oer/exercise-formats/program/match-regex-multifile/template.html new file mode 100644 index 0000000..4f8a8b2 --- /dev/null +++ b/oer/exercise-formats/program/match-regex-multifile/template.html @@ -0,0 +1,31 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_content %} +{{ slide.content |safe }} + +
+ + +{% endblock%} + + + +{% block exercise_buttons %} + + +{% endblock %} + + +{% block exercise_script %} +script program/match-regex + +{% endblock %} diff --git a/oer/exercise-formats/program/match-regex-parallel/.script.js.swp b/oer/exercise-formats/program/match-regex-parallel/.script.js.swp new file mode 100644 index 0000000..456ee3b Binary files /dev/null and b/oer/exercise-formats/program/match-regex-parallel/.script.js.swp differ diff --git a/oer/exercise-formats/program/match-regex-parallel/ExerciseHandler.py b/oer/exercise-formats/program/match-regex-parallel/ExerciseHandler.py new file mode 100644 index 0000000..48355fe --- /dev/null +++ b/oer/exercise-formats/program/match-regex-parallel/ExerciseHandler.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/match-regex-parallel loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['code'] = self.parser.get_file_content('program.c') + data['regex'] = self.parser.get_file_content('regex').strip() + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/program/match-regex-parallel/controller.py b/oer/exercise-formats/program/match-regex-parallel/controller.py new file mode 100644 index 0000000..5bb5f40 --- /dev/null +++ b/oer/exercise-formats/program/match-regex-parallel/controller.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# program/match-regex + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import subprocess +import re +import time + + +def build(ctx): + # Add filenames + allArgs = ['/usr/bin/make'] + #, self.sourcefile, "-o", "%s.exe" % self.sourcefile] + + # start subprocess in with work_path as cwd + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + return retval, errs, msgs + + +def execute(ctx): + + print("parallel execute()", file=sys.stderr) + + # if build failed, return early + if ctx.build_result[0] != 0: + return + + allArgs = ["/usr/bin/sbatch", ctx.work_path + "/job.slurm"] + + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + ctx.execute_result = (retval, errs, msgs) + + + ctx.celery_task.update_state(state='SUBMITTED TO SLURM', meta=response(ctx)) + + print("parallel execute(), before sleep", file=sys.stderr) + time.sleep(20) + print("parallel execute(), after sleep", file=sys.stderr) + + + retval = ctx.get_file_content('job.exit') + errs = ctx.get_file_content('job.err') + msgs = ctx.get_file_content('job.out') + + print( (retval, errs, msgs), file=sys.stderr) + + return retval, errs, msgs + + +def grade(ctx): + """A function that governs the grading process when different from default. + Expected is return value that indicates if the task passed or failed.""" + + print("parallel grade()", file=sys.stderr) + + # if build failed, return early and set grade to FAIL + if ctx.build_result[0] != 0: + return 'FAIL' + + ctx.execute_result = execute(ctx) + + print(ctx.data['data']['regex'], file=sys.stderr) + print(ctx.execute_result, file=sys.stderr) + if re.match(ctx.data['data']['regex'], ctx.execute_result[2]) != None: + return 'PASS' + else: + return 'FAIL' + + + +def response(ctx): + + output = "" + if ctx.build_result[0] != 0: + output = ctx.build_result[1] + else: + output = ctx.execute_result[2] + + grade = ctx.grade_result + msg = "" + return {'output': output, 'grade': grade, 'msg': msg, 'data': None} diff --git a/oer/exercise-formats/program/match-regex-parallel/script.js b/oer/exercise-formats/program/match-regex-parallel/script.js new file mode 100644 index 0000000..2c0638f --- /dev/null +++ b/oer/exercise-formats/program/match-regex-parallel/script.js @@ -0,0 +1,156 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (action, msg, output) { + console.log("show issued" + action + msg); + + html = ""; + + if (action == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (action) { + + console.log("Test submission issued.."); + console.log( $("#c-code").val() ); + + submission = {"solution": cEditor.getValue(), "action": action, "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + + $("#job-control").show(500); + setTimeout(function(){ job.status(action, job_id); }, 1000); + + }); + }; + + + job_status_countdown = 5; + job_status_retries = 1; + job.status = function (action, job_id) { + + console.log(action) + + $("#collect-results-countdown").html("(retry in " + job_status_countdown +" s)"); + + if (job_status_countdown > 0) { + job_status_countdown--; + setTimeout(function(){ job.status(action, job_id); }, 1000); + return; + } + + + e = {"dummy": "dummy value"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + $("#job-control").hide(500); + job_status_retries = 1; + response.show(action, msg, msg.data.output); + } else { + job_status_countdown = 5 * job_status_retries; + job_status_retries++; + //response.show(action, "processing...", false); + setTimeout(function(){ job.status(action, job_id); }, 1000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/program/match-regex-parallel/styles.css b/oer/exercise-formats/program/match-regex-parallel/styles.css new file mode 100644 index 0000000..0702052 --- /dev/null +++ b/oer/exercise-formats/program/match-regex-parallel/styles.css @@ -0,0 +1,9 @@ +.CodeMirror { + border: 1px solid #eee; + height: auto; + +} + +#code-editor { + font-size: 12px; +} diff --git a/oer/exercise-formats/program/match-regex-parallel/template.html b/oer/exercise-formats/program/match-regex-parallel/template.html new file mode 100644 index 0000000..ec4684f --- /dev/null +++ b/oer/exercise-formats/program/match-regex-parallel/template.html @@ -0,0 +1,56 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_content %} +{{ slide.content |safe }} + +
+ + +{% endblock%} + + + +{% block exercise_buttons %} + + + + + + + +{% endblock %} + + +{% block exercise_script %} + +{% endblock %} diff --git a/oer/exercise-formats/program/match-regex/ExerciseHandler.py b/oer/exercise-formats/program/match-regex/ExerciseHandler.py new file mode 100644 index 0000000..4bb8081 --- /dev/null +++ b/oer/exercise-formats/program/match-regex/ExerciseHandler.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/match-regex loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['code'] = self.parser.get_file_content('program.c') + data['regex'] = self.parser.get_file_content('regex').strip() + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/program/match-regex/controller.py b/oer/exercise-formats/program/match-regex/controller.py new file mode 100644 index 0000000..a456f73 --- /dev/null +++ b/oer/exercise-formats/program/match-regex/controller.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# program/match-regex + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import subprocess +import re + + +def build(ctx): + # Add filenames + allArgs = ['/usr/bin/make'] + #, self.sourcefile, "-o", "%s.exe" % self.sourcefile] + + # start subprocess in with work_path as cwd + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + return retval, errs, msgs + + +def execute(ctx): + # if build failed, return early + if ctx.build_result[0] != 0: + return + + allArgs = [ctx.programfile] + + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + return retval, errs, msgs + + +def grade(ctx): + """A function that governs the grading process when different from default. + Expected is return value that indicates if the task passed or failed.""" + + # if build failed, return early and set grade to FAIL + if ctx.build_result[0] != 0: + return 'FAIL' + + ctx.execute_result = execute(ctx) + + print(ctx.data['data']['regex'], file=sys.stderr) + print(ctx.execute_result, file=sys.stderr) + if re.match(ctx.data['data']['regex'], ctx.execute_result[2]) != None: + return 'PASS' + else: + return 'FAIL' + + + +def response(ctx): + + output = "" + if ctx.build_result[0] != 0: + output = ctx.build_result[1] + else: + output = ctx.execute_result[2] + + grade = ctx.grade_result + msg = "" + return {'output': output, 'grade': grade, 'msg': msg, 'data': None} diff --git a/oer/exercise-formats/program/match-regex/script.js b/oer/exercise-formats/program/match-regex/script.js new file mode 100644 index 0000000..208f30e --- /dev/null +++ b/oer/exercise-formats/program/match-regex/script.js @@ -0,0 +1,138 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (action) { + + console.log("Test submission issued.."); + console.log( $("#c-code").val() ); + + submission = {"solution": cEditor.getValue(), "cmd": "run.sh", "action": action, "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + setTimeout(function(){ job.status(action, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type) + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/program/match-regex/styles.css b/oer/exercise-formats/program/match-regex/styles.css new file mode 100644 index 0000000..0702052 --- /dev/null +++ b/oer/exercise-formats/program/match-regex/styles.css @@ -0,0 +1,9 @@ +.CodeMirror { + border: 1px solid #eee; + height: auto; + +} + +#code-editor { + font-size: 12px; +} diff --git a/oer/exercise-formats/program/match-regex/template.html b/oer/exercise-formats/program/match-regex/template.html new file mode 100644 index 0000000..63b3917 --- /dev/null +++ b/oer/exercise-formats/program/match-regex/template.html @@ -0,0 +1,31 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_content %} +{{ slide.content |safe }} + +
+ + +{% endblock%} + + + +{% block exercise_buttons %} + + +{% endblock %} + + +{% block exercise_script %} + +{% endblock %} diff --git a/oer/exercise-formats/program/scriptgrade-multifile/ExerciseHandler.py b/oer/exercise-formats/program/scriptgrade-multifile/ExerciseHandler.py new file mode 100644 index 0000000..8caba65 --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade-multifile/ExerciseHandler.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +print("Handler program/scriptgrade loaded!") + + +class ExerciseHandler(object): + def __init__(self): + print("ExerciseHandler program/scriptgrade") diff --git a/oer/exercise-formats/program/scriptgrade-parallel/ExerciseHandler.py b/oer/exercise-formats/program/scriptgrade-parallel/ExerciseHandler.py new file mode 100644 index 0000000..8caba65 --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade-parallel/ExerciseHandler.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +print("Handler program/scriptgrade loaded!") + + +class ExerciseHandler(object): + def __init__(self): + print("ExerciseHandler program/scriptgrade") diff --git a/oer/exercise-formats/program/scriptgrade/ExerciseHandler.py b/oer/exercise-formats/program/scriptgrade/ExerciseHandler.py new file mode 100644 index 0000000..0750e8e --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade/ExerciseHandler.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/scriptgrade loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.grading = True + + item.content = self.parser.get_exercise_content() + data['code'] = self.parser.get_file_content('program.c') + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/program/scriptgrade/controller.py b/oer/exercise-formats/program/scriptgrade/controller.py new file mode 100644 index 0000000..6e69a06 --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade/controller.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + + +import sys +import subprocess +import re + +def build(ctx): + # Add filenames + allArgs = ['/usr/bin/make'] + #, self.sourcefile, "-o", "%s.exe" % self.sourcefile] + + # start subprocess in with work_path as cwd + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + return retval, errs, msgs + + +def execute(ctx): + allArgs = ['/usr/bin/make', 'execute'] + allArgs = ['./execute.sh'] + + # start subprocess in with work_path as cwd + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + return retval, errs, msgs + + +def grade(ctx): + print("GRADING!!", file=sys.stderr) + + # if build failed, return early and set grade to FAIL + if ctx.build_result[0] != 0: + return 'FAIL' + + print(ctx.execute_result, file=sys.stderr) + + allArgs = ['/usr/bin/make', 'execute'] + allArgs = ['./test.sh'] + + # start subprocess in with work_path as cwd + p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) + msgs,errs = p.communicate() + retval = p.wait() + + errs = errs.decode("utf-8") + msgs = msgs.decode("utf-8") + + + ctx.execute_result = (retval, errs, msgs) + + print(ctx.execute_result, file=sys.stderr) + + if re.match('FAIL', msgs, re.MULTILINE) != None: + return 'FAIL' + else: + return 'PASS' + + +def response(ctx): + output = "" + + + print(ctx.build_result, file=sys.stderr) + print(ctx.execute_result, file=sys.stderr) + print(ctx.grade_result, file=sys.stderr) + + + if ctx.build_result[0] != 0: + output = ctx.build_result[1] + else: + output = ctx.execute_result[2] + + grade = ctx.grade_result + msg = "" + return {'output': output, 'grade': grade, 'msg': msg, 'data': None} + diff --git a/oer/exercise-formats/program/scriptgrade/script.js b/oer/exercise-formats/program/scriptgrade/script.js new file mode 100644 index 0000000..208f30e --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade/script.js @@ -0,0 +1,138 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (action) { + + console.log("Test submission issued.."); + console.log( $("#c-code").val() ); + + submission = {"solution": cEditor.getValue(), "cmd": "run.sh", "action": action, "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + setTimeout(function(){ job.status(action, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type) + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/program/scriptgrade/styles.css b/oer/exercise-formats/program/scriptgrade/styles.css new file mode 100644 index 0000000..0702052 --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade/styles.css @@ -0,0 +1,9 @@ +.CodeMirror { + border: 1px solid #eee; + height: auto; + +} + +#code-editor { + font-size: 12px; +} diff --git a/oer/exercise-formats/program/scriptgrade/template.html b/oer/exercise-formats/program/scriptgrade/template.html new file mode 100644 index 0000000..63b3917 --- /dev/null +++ b/oer/exercise-formats/program/scriptgrade/template.html @@ -0,0 +1,31 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_content %} +{{ slide.content |safe }} + +
+ + +{% endblock%} + + + +{% block exercise_buttons %} + + +{% endblock %} + + +{% block exercise_script %} + +{% endblock %} diff --git a/oer/exercise-formats/text/html/ExerciseHandler.py b/oer/exercise-formats/text/html/ExerciseHandler.py new file mode 100644 index 0000000..bcc48a9 --- /dev/null +++ b/oer/exercise-formats/text/html/ExerciseHandler.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import json + +print("Handler program/match-regex loaded!") + + +# helper + + +class ExerciseHandler(object): + def __init__(self, parser=None): + self.parser = parser + self.data = {'code': ''} + print("ExerciseHandler program/match-regex") + print("parser.path", parser.path) + + + item = self.parser.item + data = self.data + + # enable grading for this exercise type + item.content = self.parser.get_exercise_content() + item.grading = False + + + item.data = json.dumps(self.data) + item.save() diff --git a/oer/exercise-formats/text/html/controller.py b/oer/exercise-formats/text/html/controller.py new file mode 100644 index 0000000..0e8d59f --- /dev/null +++ b/oer/exercise-formats/text/html/controller.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +# program/match-regex + + +# Standardized types do not require authors to specify any control script as +# it can be generated on import. However when provided it will overwrite the +# default behaivior. + +import sys +import subprocess + + + +def build(context): + pass + +def run(context): + pass + + +# The following code serves to illustrate what will be generated automaticly +# for simple programming tasks in C. +# AUTO-GENERATED CODE: +def grade(context): + """A function that governs the grading process when different from default. + Expected is return value that indicates if the task passed or failed.""" + print("default GRADE HANDLER says hello ;) context ist: %s" % context, file=sys.stderr) + return "hoho ;)" + + diff --git a/oer/exercise-formats/text/html/script.js b/oer/exercise-formats/text/html/script.js new file mode 100644 index 0000000..44b0347 --- /dev/null +++ b/oer/exercise-formats/text/html/script.js @@ -0,0 +1,138 @@ +$(document).ready(function () { + + response = {}; + + response.show = function (type, msg, output) { + console.log("show issued" + type + msg); + + html = ""; + + if (type == "test") { + + } else { + if (msg.data.grade == "PASS") { + html = ''; + $("#continue").prop( "disabled", false); + } else if (msg.data.grade == "FAIL") { + html = ''; + } else { + // assume test + //html = msg; + // a possible message that is generated yb the server to give tips? + } + } + + + console.log(output) + if ( output == "" ) { + output = " " + } + + if ( output != false) { + console.log("output is not false") + $("#output-wrapper").show(500); + $("#output").html(output); + } + + $("#response").hide().html(html).show(500); + + + $("#submit-test").prop( "disabled", false); + $("#submit-grade").prop( "disabled", false); + + } + + + job = {} + job.submit = function (type) { + + console.log("Test submission issued.."); + console.log( $("#c-code").val() ); + + submission = {"solution": cEditor.getValue(), "cmd": "run.sh", "type": type, "slide": window.data.slide}; + submission_json = JSON.stringify(submission); + + console.log(submission_json) + + $.ajax({ + method: "POST", + url: "/api/rest/job/new/", + contentType: 'application/json', + data: submission_json + }) + .done(function( msg ) { + console.log("Job submitted: " + msg ); + console.log(msg); + + job_id = msg['id']; + setTimeout(function(){ job.status(type, job_id); }, 1000); + + }); + }; + + job.status = function (type, job_id) { + + console.log(type) + + e = {"blub": "hm"}; + json_data = JSON.stringify(e); + + $.ajax({ + method: "GET", + url: "/api/rest/job/" + job_id + "/", + contentType: 'application/json', + }) + .done(function( msg ) { + console.log("Status received: " + msg ); + console.log(msg); + + if ( msg.status == 'SUCCESS' ) { + response.show(type, msg, msg.data.output); + } else { + response.show(type, "processing...", false); + setTimeout(function(){ job.status(type, job_id); }, 3000); + } + + }); + + }; + + + $("#submit-test").click(function(event) { + $("#submit-test").prop( "disabled", true); + job.submit("test"); + }); + + $("#submit-grade").click(function(event) { + $("#submit-grade").prop( "disabled", true); + job.submit("grade"); + }); + + + $("#exercise-choices a.list-group-item").click(function(event) { + //event.preventDefault() + //$("#submit-test").prop( "disabled", true); + //job.submit("test"); + + + target = event.target + + + if ( $(target).is('input') ) { + target = $(event.target).parent()[0] + } else { + // also check/uncheck when clicking surounding + } + + //if ( $(target).children("input").attr('type') == 'radio' ) { + // $(target).parent().children(".list-group-item-success").removeClass("list-group-item-success"); + //} + + console.log(target) + $(target).children("input").each(function () { this.checked = !this.checked; console.log(this) }); + //$(target).toggleClass("list-group-item-success"); + + }); + +}); + diff --git a/oer/exercise-formats/text/html/styles.css b/oer/exercise-formats/text/html/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/oer/exercise-formats/text/html/template.html b/oer/exercise-formats/text/html/template.html new file mode 100644 index 0000000..575fc00 --- /dev/null +++ b/oer/exercise-formats/text/html/template.html @@ -0,0 +1,18 @@ +{% extends "courses/course.html" %} +{% load staticfiles %} +{% load main_extras %} + + +{% block exercise_content %} +{{ slide.content |safe }} +{% endblock%} + + + +{% block exercise_buttons %} +{% endblock %} + + +{% block exercise_script %} + +{% endblock %} diff --git a/oer/exercise-formats/video/youtube/scripts.js b/oer/exercise-formats/video/youtube/scripts.js new file mode 100644 index 0000000..e69de29 diff --git a/oer/exercise-formats/video/youtube/styles.css b/oer/exercise-formats/video/youtube/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/oer/exercise-formats/video/youtube/template.html b/oer/exercise-formats/video/youtube/template.html new file mode 100644 index 0000000..b1a2e41 --- /dev/null +++ b/oer/exercise-formats/video/youtube/template.html @@ -0,0 +1,4 @@ +
+ +
+ diff --git a/scripts/update-courses.sh b/scripts/update-courses.sh new file mode 100755 index 0000000..be877a5 --- /dev/null +++ b/scripts/update-courses.sh @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +source /data/run/virtualenv/bin/activate +cd /data/src + +export GENERATED_PATH=/data/run/oer +export OER_SRC_DIR=/data/oer +export PLATFORM_PATH=/data/src +python3 manage.py import-courses --sources=/data/oer/courses --formats=/data/oer/exercise-formats/ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..7876932 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,22 @@ + + +all: + @echo Use one of the other targets. + +reset: + rm -f db.sqlite3 + find . -iname '*sw[po]' -print -delete + find . -iname '__pycache__' -print -exec rm -r "{}" \; + find . -iname 'migrations' -print -exec rm -r "{}" \; + +setup-devel: + ./setup-devel + +test: + ./manage.py test courses + + +migrations: + source ../virtualenv/bin/activate + ./manage.py makemigrations # check models for changes + ./manage.py migrate # apply to database diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..4a11f6e --- /dev/null +++ b/src/README.md @@ -0,0 +1,45 @@ +# Requirements + + * Django + * Django REST Framework + * Python Social Auth + +An easy way to install the dependencies is provided by using pip. Always +consider to use virtualenv, be it for testing or for deployment. + + mkdir virtualenv + virtualenv -p python3 ./virtualenv + source ./virtualenv/bin/activate + pip3 install -U -r requirements.txt + +NOTE: When working on the project make sure to source the ./bin/activate file +to set the environment correctly. + +# Development/Test Environment + +For convienience during testing you can use some of the helpers, provided +either through the Makefile or through shell scripts wrapping common actions with Django. +If your familier with Django you may also iterface as usual using the +manage.py script. + +E.g. to start the server you can simply run: + + ./run-testserver + +# Deployment + +The testserver should not be used for production systems. Also instead of using +sqlite PostgreSQL should be installed as the database backend. + +## Tests + +Before you deploy the app, you should run the tests provided to make sure everything +works as expected. Start the + + make test + +OR + + python manage.py test courses + python manage.py test rest + diff --git a/src/courses/__init__.py b/src/courses/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/courses/admin.py b/src/courses/admin.py new file mode 100644 index 0000000..b2b3ea0 --- /dev/null +++ b/src/courses/admin.py @@ -0,0 +1,75 @@ +from django.contrib import admin + +# Register your models here. + +from .models import Course +from .models import Section +from .models import Slide + + +# in case the ORM is registered directly all fields will be shown +#admin.site.register(Course) + + +class SlideInline(admin.StackedInline): + model = Slide + extra = 3 + +class SectionInline(admin.TabularInline): + model = Section + extra = 3 + + +class SectionsInline(admin.TabularInline): + model = Course.sections.through + +class SlidesInline(admin.TabularInline): + model = Section.slides.through + + + +class SectionAdmin(admin.ModelAdmin): + inlines = [ + SlidesInline, + ] + exclude = ('slides',) + +# otherwise "fields" serves as a whitelist +class CourseAdmin(admin.ModelAdmin): + #fieldsets = [ + # (None, {'fields': ['title', 'description', 'source_path']}), + #] + #inlines = [SectionInline] + inlines = [ + SectionsInline, + ] + exclude = ('sections',) + + + +# otherwise "fields" serves as a whitelist +#class SectionAdmin(admin.ModelAdmin): +# #list_display = ('title') +# fieldsets = [ +# (None, {'fields': ['title', 'description']}), +# # ("Meta", {'fields': ['pub_date'], 'classes': ['collapse']}), +# ] +# #inlines = [SlideInline] + + +class SlideAdmin(admin.ModelAdmin): + list_display = ('title', 'description') + + + +admin.site.register(Course, CourseAdmin) +admin.site.register(Section, SectionAdmin) +admin.site.register(Slide, SlideAdmin) + +# Use django default admin +#admin.site.register(Course) +#admin.site.register(Section) +#admin.site.register(Slide) + + + diff --git a/src/courses/migrations/0001_initial.py b/src/courses/migrations/0001_initial.py new file mode 100644 index 0000000..92a6476 --- /dev/null +++ b/src/courses/migrations/0001_initial.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2016-04-20 14:27 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Course', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('description', models.CharField(max_length=200)), + ('source_path', models.CharField(blank=True, default='', max_length=500, null=True)), + ], + ), + migrations.CreateModel( + name='Section', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('description', models.CharField(max_length=200)), + ('source_path', models.CharField(blank=True, default='', max_length=500, null=True)), + ], + options={ + 'ordering': ['source_path'], + }, + ), + migrations.CreateModel( + name='Slide', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, default='', max_length=200, null=True)), + ('title_short', models.CharField(blank=True, default='', max_length=200, null=True)), + ('description', models.CharField(blank=True, default='', max_length=200, null=True)), + ('icon', models.CharField(blank=True, max_length=200, null=True)), + ('slide_type', models.CharField(default='text/html', max_length=200)), + ('content', models.TextField(blank=True, default='', null=True)), + ('solution', models.TextField(blank=True, default='', null=True)), + ('grading', models.BooleanField(default=False)), + ('data', models.TextField(blank=True, default='{}', null=True)), + ('source_path', models.CharField(blank=True, default='', max_length=500, null=True)), + ], + options={ + 'ordering': ['source_path'], + }, + ), + migrations.CreateModel( + name='UserCourse', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course')), + ('progress_section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Section')), + ('progress_slide', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Slide')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserEvent', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timestamp', models.DateTimeField(verbose_name='timestamp')), + ('event_type', models.TextField()), + ('event_data', models.TextField()), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserSolution', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_path', models.CharField(blank=True, default='', max_length=500, null=True)), + ('data', models.TextField(blank=True, default='{}', null=True)), + ('date', models.DateTimeField(verbose_name='date submitted')), + ('passed', models.BooleanField()), + ('tries', models.PositiveSmallIntegerField()), + ('duration', models.DurationField()), + ('slide', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Slide')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='section', + name='slides', + field=models.ManyToManyField(to='courses.Slide'), + ), + migrations.AddField( + model_name='course', + name='sections', + field=models.ManyToManyField(to='courses.Section'), + ), + ] diff --git a/src/courses/migrations/0002_auto_20160801_1444.py b/src/courses/migrations/0002_auto_20160801_1444.py new file mode 100644 index 0000000..86dc48e --- /dev/null +++ b/src/courses/migrations/0002_auto_20160801_1444.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.8 on 2016-08-01 14:44 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('courses', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='course', + name='course_type', + field=models.CharField(default='text/html', max_length=200), + ), + migrations.AddField( + model_name='section', + name='section_type', + field=models.CharField(default='text/html', max_length=200), + ), + ] diff --git a/src/courses/migrations/__init__.py b/src/courses/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/courses/models.py b/src/courses/models.py new file mode 100644 index 0000000..bf97dd8 --- /dev/null +++ b/src/courses/models.py @@ -0,0 +1,96 @@ +import datetime + +from django.db import models +from django.utils import timezone + +#from django.contrib.postgres.fields import JSONField + +from django.contrib.auth.models import User + + +# Create your models here. +class Slide(models.Model): + title = models.CharField(max_length=200, default='', null=True, blank=True) + title_short = models.CharField(max_length=200, default='', null=True, blank=True) + description = models.CharField(max_length=200, default='', null=True, blank=True) + slide_type = models.CharField(max_length=200, default='text/html') + icon = models.CharField(max_length=200, null=True, blank=True) + content = models.TextField(default='', null=True, blank=True) + solution = models.TextField(default='', null=True, blank=True) + grading = models.BooleanField(default=False) + #data = JSONField() + data = models.TextField(default='{}', null=True, blank=True) + source_path = models.CharField(max_length=500, default='', null=True, blank=True) + + class Meta: + ordering = ['source_path'] + + def __str__(self): + return self.title + + + + +class Section(models.Model): + #course = models.ForeignKey('Course') # many to many, on_delete=models.CASCADE? + title = models.CharField(max_length=200) + description = models.CharField(max_length=200) + section_type = models.CharField(max_length=200, default='text/html') + source_path = models.CharField(max_length=500, default='', null=True, blank=True) + + slides = models.ManyToManyField(Slide) + + class Meta: + ordering = ['source_path'] + + + def __str__(self): + return self.title + + + +class Course(models.Model): + title = models.CharField(max_length=200) + description = models.CharField(max_length=200) + course_type = models.CharField(max_length=200, default='text/html') + source_path = models.CharField(max_length=500, default='', null=True, blank=True) + + sections = models.ManyToManyField(Section) + + + + def __str__(self): + return self.title + + + + + +# User stuff reliated to courses +class UserCourse(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + course = models.ForeignKey(Course, on_delete=models.CASCADE) + progress_section = models.ForeignKey(Section, on_delete=models.CASCADE) + progress_slide = models.ForeignKey(Slide, on_delete=models.CASCADE) + + +class UserSolution(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + slide = models.ForeignKey(Slide, on_delete=models.CASCADE) + source_path = models.CharField(max_length=500, default='', null=True, blank=True) + + data = models.TextField(default='{}', null=True, blank=True) + + date = models.DateTimeField('date submitted') + passed = models.BooleanField() + tries = models.PositiveSmallIntegerField() + duration = models.DurationField() + + +class UserEvent(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + timestamp = models.DateTimeField('timestamp') + event_type = models.TextField() + event_data = models.TextField() + + #course = models.ForeignKey('Course') # many to many, on_delete=models.CASCADE? diff --git a/src/courses/static/courses/eventstream.js b/src/courses/static/courses/eventstream.js new file mode 100644 index 0000000..72fda53 --- /dev/null +++ b/src/courses/static/courses/eventstream.js @@ -0,0 +1,172 @@ +$(document).ready(function () { + + window.eventstream_verbose = false; + debug = {} + debug.log = function(msg) { + if (window.eventstream_verbose) + console.log(msg) + } + + function getXPath( element ) + { + var xpath = ''; + for ( ; element && element.nodeType == 1; element = element.parentNode ) + { + var id = $(element.parentNode).children(element.tagName).index(element) + 1; + id > 1 ? (id = '[' + id + ']') : (id = ''); + xpath = '/' + element.tagName.toLowerCase() + id + xpath; + } + return xpath; + } + + + /** + * Log the activity for later analysis to improve course structure. + */ + push_event = function (type, d) { + return; + e = {} + e['data'] = d + e['type'] = type + json_data = JSON.stringify(e) + debug.log(json_data) + + $.ajax({ + method: "POST", + url: "/api/rest/event", + contentType: 'application/json', + data: json_data + }) + .done(function( msg ) { + debug.log("Event logged:"); + debug.log(msg ); + }); + } + + window.push_event = push_event; + + + + // Why take the start time?, jquery as there is IE8 issues + now = $.now() + + + /** + * MOUSE MOVEMENTS + * + * For very detailed analysis tracking mouse movements can be enabled. + * Note however that this will create vast amounts of events which may + * hold little value for didactic improvements. + * + * Alternative: push mouse trace with click, to see what lead to the click? + */ + /* */ + mousemove_buffer = []; + mousemove_buffer_size = 100; + mousemove_counter = mousemove_buffer_size; + + $(document).mousemove(function( event ) { + var pageCoords = "( " + event.pageX + ", " + event.pageY + " )"; + var clientCoords = "( " + event.clientX + ", " + event.clientY + " )"; + var screenCoords = "( " + event.screenX + ", " + event.screenY + " )"; + + //console.log("---"); + //console.log( pageCoords ); + //console.log( clientCoords ); + + mousemove_buffer.push([now+event.timeStamp, event.pageX, event.pageY]) + mousemove_counter--; + + if (mousemove_counter < 0) + { + push_event("mousemove", mousemove_buffer) + mousemove_buffer = [] + mousemove_counter = mousemove_buffer_size; + } + + }); + + + + $(window).resize(function(event) { + var w = $(window).width(); + var h = $(window).height(); + + e = {'width': w, 'height': h}; + + mousemove_buffer.push([now+event.timeStamp, "resize", w, h]) + push_event("resize", e) + }); + + + + $(window).scroll(function(event) { + var t = $(window).scrollTop(); + var l = $(window).scrollLeft(); + + mousemove_buffer.push(["scroll", t, l]) + + e = {'top': t, 'left': l}; + push_event("scroll", e) + }); + + + + /** + * CLICK EVENTS (window) + * + * Similar to the mouse movement it may be useful to collect click data, + * though click data maybe somewhat more meaningful as it stands for a + * concrete user interaction + * */ + $(document).click(function(event) { + //debug.log(event) + //debug.log(event.target) + + //var pageCoords = "( " + event.pageX + ", " + event.pageY + " )"; + //var clientCoords = "( " + event.clientX + ", " + event.clientY + " )"; + //var screenCoords = "( " + event.screenX + ", " + event.screenY + " )"; + + var w = $(window).width(); + var h = $(window).height(); + + var t = $(window).scrollTop(); + var l = $(window).scrollLeft(); + + mousemove_buffer.push([now+event.timeStamp, "click", event.pageX, event.pageY]) + + x = getXPath(event.target); + + + // get editor line, char + editor = "none"; + if ( window.cEditor != null ) { + editor = cEditor.getCursor(); + } + + e = {"xpath": x, "pos": [event.pageX, event.pageX], "viewport": [w, h], "scroll": [t, l], "editor": editor} + + push_event("click", e) + }); + + + + + + + // TODO + // Start/Stop/Jump Video => may hint at problems, convienient when continueing + + + /** + * YOUTUBE VIDEO EVENTS + * + * Understanding how users consume the learning videos seems to have great + * potential in improving the videos. E.g. if many people pause or rewatch + * a part of the video this may indeicate a problem. + */ + + + + +}); diff --git a/src/courses/static/courses/index.html b/src/courses/static/courses/index.html new file mode 100644 index 0000000..6f49a0d --- /dev/null +++ b/src/courses/static/courses/index.html @@ -0,0 +1,141 @@ + + + + + + + + + + + + Off Canvas Template for Bootstrap + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+

+ +

+
+

Hello, world!

+

This is an example to show the potential of an offcanvas layout pattern in Bootstrap. Try some responsive-range viewport sizes to see it in action.

+
+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+

Heading

+

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

+

View details »

+
+
+
+ + + + + +
+ +
+ +
+

© Company 2014

+
+ +
+ + + + + + + + + + + + + diff --git a/src/courses/static/courses/offcanvas.css b/src/courses/static/courses/offcanvas.css new file mode 100644 index 0000000..2a72199 --- /dev/null +++ b/src/courses/static/courses/offcanvas.css @@ -0,0 +1,59 @@ +/* + * Style tweaks + * -------------------------------------------------- + */ +html, +body { + overflow-x: hidden; /* Prevent scroll on narrow devices */ +} +body { + padding-top: 70px; +} +footer { + padding: 30px 0; +} + +/* + * Off Canvas + * -------------------------------------------------- + */ +@media screen and (max-width: 767px) { + .row-offcanvas { + position: relative; + -webkit-transition: all .25s ease-out; + -o-transition: all .25s ease-out; + transition: all .25s ease-out; + } + + .row-offcanvas-right { + right: 0; + } + + .row-offcanvas-left { + left: 0; + } + + .row-offcanvas-right + .sidebar-offcanvas { + right: -50%; /* 6 columns */ + } + + .row-offcanvas-left + .sidebar-offcanvas { + left: -50%; /* 6 columns */ + } + + .row-offcanvas-right.active { + right: 50%; /* 6 columns */ + } + + .row-offcanvas-left.active { + left: 50%; /* 6 columns */ + } + + .sidebar-offcanvas { + position: absolute; + top: 0; + width: 50%; /* 6 columns */ + } +} diff --git a/src/courses/static/courses/offcanvas.js b/src/courses/static/courses/offcanvas.js new file mode 100644 index 0000000..d2f37f2 --- /dev/null +++ b/src/courses/static/courses/offcanvas.js @@ -0,0 +1,5 @@ +$(document).ready(function () { + $('[data-toggle="offcanvas"]').click(function () { + $('.row-offcanvas').toggleClass('active') + }); +}); \ No newline at end of file diff --git a/src/courses/templates/courses/course.html b/src/courses/templates/courses/course.html new file mode 100644 index 0000000..425fe06 --- /dev/null +++ b/src/courses/templates/courses/course.html @@ -0,0 +1,245 @@ +{% load staticfiles %} +{% load main_extras %} + + + + + + + + + + + + + {{ course.title }} + + + + + + + + + + + + + + + + + + + + + + + + + +{% block exercise_head %} + +{% endblock %} + + + + + + + {% include "frontend/navbar.html" %} + + +
+
+
 
+
+ + +
+ + +{% if not user.is_authenticated %} + +{% endif %} + + + +
+ + + +
+ +
+ +
+ + + +
+ + + +
+ + + +

+ +

+ + + +
+ +{% if slide %} + {% block exercise_content_before %} + {% endblock %} + + {% block exercise_content %} + {{ slide.content |safe }} + {% endblock %} +{% else %} +

No slide content provided yet.

+{% endif %} + +{% comment %} +slide.data: {{ slide.data }}
+slide_data: {{ slide_data }}
+{% endcomment %} + + +
+ +{% if next_slide.slide %} +{% csrf_token %} +
+ +
+{% endif %} + + +{% if slide.grading %} +{% block exercise_buttons %} + +{% endblock %} +{% else %} + +{% endif %} + + + + + + +
+
+ +{% block exercise_content_after %} +{% endblock %} + +
+ +{% block exercise_response_before %} +{% endblock %} + +{% block exercise_response %} + +{% endblock %} + + + +{% block exercise_response_after %} +{% endblock %} + +
+ + + +
+
+ +
+ + {% include "frontend/footer.html" %} + + +
+ + +{% if slide %} + + +{% endif %} + + + + + + + + + + + + + + + + + + +{% block exercise_script %} + +{% endblock %} + + + + diff --git a/src/courses/templates/courses/course_list.html b/src/courses/templates/courses/course_list.html new file mode 100644 index 0000000..342c109 --- /dev/null +++ b/src/courses/templates/courses/course_list.html @@ -0,0 +1,7 @@ +

Courses

+ +
    +{% for contact in object_list %} +
  • {{ contact }}
  • +{% endfor %} +
diff --git a/src/courses/templates/courses/index.html b/src/courses/templates/courses/index.html new file mode 100644 index 0000000..fc8068a --- /dev/null +++ b/src/courses/templates/courses/index.html @@ -0,0 +1,3 @@ +{% load staticfiles %} + +course index/list? diff --git a/src/courses/tests.py b/src/courses/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/src/courses/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/courses/urls.py b/src/courses/urls.py new file mode 100644 index 0000000..8a570b2 --- /dev/null +++ b/src/courses/urls.py @@ -0,0 +1,30 @@ +""" URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.8/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Add an import: from blog import urls as blog_urls + 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) +""" +from django.conf.urls import include, url +from django.contrib import admin + +from courses import views + +app_name = "courses" + +urlpatterns = [ + url(r'^$', views.index, name='index'), + url(r'^(?P[0-9]+)/$', views.course, name='course'), + url(r'^(?P[0-9]+)/(?P[0-9]+)/$', views.section, name='section'), + url(r'^(?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)/$', views.slide, name='slide'), + + url(r'^listview$', views.ListCourseView.as_view(), name='courses-list'), +] diff --git a/src/courses/views.py b/src/courses/views.py new file mode 100644 index 0000000..9d69060 --- /dev/null +++ b/src/courses/views.py @@ -0,0 +1,180 @@ +from __future__ import print_function + +from django.shortcuts import render +from django.shortcuts import get_object_or_404 + +from django.urls import reverse + +from django.http import HttpResponse +from django.http import HttpResponseRedirect + +from django import template +from django.template.defaultfilters import stringfilter + +# Class Based Views (CBV) +from django.views.generic import View +from django.views.generic import ListView + + +from .models import Course +from .models import Section +from .models import Slide +from .models import UserCourse +from .models import UserSolution + +import sys +import json + +class ListCourseView(ListView): + model = Course + + +############################################################################### +def index(request): + data = {} + return render(request, 'courses/index.html') + +############################################################################### +def course(request, cid): + course = get_object_or_404(Course, pk=cid) + first_section = course.sections.first() + first_slide = first_section.slides.first() + + if request.user.is_authenticated(): + try: + # when the user is merely opening the course, jump the last active section (better: last incomplete?) + user_course = UserCourse.objects.get(course=course, user=request.user) + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, user_course.progress_section.id, user_course.progress_slide.id))) + except UserCourse.DoesNotExist: + # usfrom django import template + # also redirect to course beginning + user_course = UserCourse.objects.create(course=course, user=request.user, progress_section=first_section, progress_slide=first_slide) + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, first_section.id, first_slide.id))) + else: + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, first_section.id, first_slide.id))) + + + data = {'course': course} + return render(request, 'courses/course.html', data) + + +############################################################################### +def section(request, cid, seid): + course = get_object_or_404(Course, pk=cid) + section = get_object_or_404(Section, pk=seid) + first_slide = section.slides.first() + + if request.user.is_authenticated(): + try: + user_course = UserCourse.objects.get(course=course, user=request.user) + + if section.id == user_course.progress_section.id: + # only redirect if progress was made in this sections + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, user_course.progress_section.id, user_course.progress_slide.id))) + else: + # otherwise switch to first slide in section + first_slide = section.slides.first() + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, section.id, first_slide.id))) + + except UserCourse.DoesNotExist: + # TODO how are direct visitors handled? + pass + else: + return HttpResponseRedirect(reverse('courses:slide', args=(course.id, section.id, first_slide.id))) + + data = {'course': course} + return render(request, 'courses/course.html', data) + + +############################################################################### +def slide(request, cid, seid, slid): + """ The slide view serves the smallest servable unit of material to the + user. In principle a single slide is meant to provide + """ + course = get_object_or_404(Course, pk=cid) + section = get_object_or_404(Section, pk=seid) + slide = get_object_or_404(Slide, pk=slid) + + + + if request.user.is_authenticated(): + try: + user_course = UserCourse.objects.get(course=course, user=request.user) + # simply update last user_course action + user_course.progress_section = section + user_course.progress_slide = slide + user_course.save() + + except UserCourse.DoesNotExist: + # TODO Should direct visitors get a special treatment? + pass + + + + user_solution = None + if request.user.is_authenticated(): + try: + user_solution = UserSolution.objects.get(slide=slide, user=request.user) + + except UserSolution.DoesNotExist: + # TODO Should direct visitors get a special treatment? + pass + + + print(user_solution, file=sys.stderr) + + + result = request + print(result, file=sys.stderr) + print(dir(result), file=sys.stderr) + + # determine next slide, as necessary for the navigation + next_slide = {'course': course, 'section': None, 'slide': None} + matched_slide = False + slides = section.slides.all() + for s in slides: + if matched_slide: + next_slide['slide'] = s + next_slide['section'] = section + break; + + if slide.id == s.id: + matched_slide = True + + # looks like the slide was the last for this section find next section + if next_slide['slide'] == None: + matched_section = False + sections = course.sections.all() + for sec in sections: + if matched_section: + next_slide['slide'] = sec.slides.first() + next_slide['section'] = sec + break; + + if section.id == sec.id: + matched_section = True + + try: + slide_data = json.loads(slide.data) + except: + slide_data = "Exception!" + + + try: + user_solution_data = json.loads(user_solution.data) + except: + user_solution_data = "Exception!" + + + + + data = {'course': course, 'section': section, 'slide': slide, 'next_slide': next_slide, 'slide_data': slide_data, 'user_solution_data': user_solution_data} +# return render(request, 'courses/course.html', data) + + try: + template_path = 'generated_exercises/%s/template.html' % (slide.slide_type) + print(template_path, file=sys.stderr) + template.loader.get_template(template_path) + return render(request, template_path, data) + except template.TemplateDoesNotExist: + return render(request, 'courses/course.html', data) diff --git a/src/frontend/__init__.py b/src/frontend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/admin.py b/src/frontend/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/src/frontend/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/src/frontend/models.py b/src/frontend/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/src/frontend/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/src/frontend/static/frontend/dashboard/dashboard.css b/src/frontend/static/frontend/dashboard/dashboard.css new file mode 100644 index 0000000..e0e3632 --- /dev/null +++ b/src/frontend/static/frontend/dashboard/dashboard.css @@ -0,0 +1,105 @@ +/* + * Base structure + */ + +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; +} + + +/* + * Global add-ons + */ + +.sub-header { + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +/* + * Top navigation + * Hide default border to remove 1px line. + */ +.navbar-fixed-top { + border: 0; +} + +/* + * Sidebar + */ + +/* Hide for mobile, show later */ +.sidebar { + display: none; +} +@media (min-width: 768px) { + .sidebar { + position: fixed; + top: 51px; + bottom: 0; + left: 0; + z-index: 1000; + display: block; + padding: 20px; + overflow-x: hidden; + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + background-color: #f5f5f5; + border-right: 1px solid #eee; + } +} + +/* Sidebar navigation */ +.nav-sidebar { + margin-right: -21px; /* 20px padding + 1px border */ + margin-bottom: 20px; + margin-left: -20px; +} +.nav-sidebar > li > a { + padding-right: 20px; + padding-left: 20px; +} +.nav-sidebar > .active > a, +.nav-sidebar > .active > a:hover, +.nav-sidebar > .active > a:focus { + color: #fff; + background-color: #428bca; +} + + +/* + * Main content + */ + +.main { + padding: 20px; +} +@media (min-width: 768px) { + .main { + padding-right: 40px; + padding-left: 40px; + } +} +.main .page-header { + margin-top: 0; +} + + +/* + * Placeholder dashboard ideas + */ + +.placeholders { + margin-bottom: 30px; + text-align: center; +} +.placeholders h4 { + margin-bottom: 0; +} +.placeholder { + margin-bottom: 20px; +} +.placeholder img { + display: inline-block; + border-radius: 50%; +} diff --git a/src/frontend/static/frontend/drawing_credit.png b/src/frontend/static/frontend/drawing_credit.png new file mode 100644 index 0000000..7417917 Binary files /dev/null and b/src/frontend/static/frontend/drawing_credit.png differ diff --git a/src/frontend/static/frontend/drawing_credit.svg b/src/frontend/static/frontend/drawing_credit.svg new file mode 100644 index 0000000..1c8c861 --- /dev/null +++ b/src/frontend/static/frontend/drawing_credit.svg @@ -0,0 +1,933 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + + + + + Created by Creative Stall + from the Noun Project + + + + + + + + + + + + + + + + + + Created by Creative Stall + from the Noun Project + + + + + + + + + + + + + + Created by Creative Stall + from the Noun Project + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + + + + + + + + + + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + Created by Lloyd Humphreys + from the Noun Project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Created by alessandra antonetti + from the Noun Project + + + diff --git a/src/frontend/static/frontend/drawing_nocredit.png b/src/frontend/static/frontend/drawing_nocredit.png new file mode 100644 index 0000000..92a9d0b Binary files /dev/null and b/src/frontend/static/frontend/drawing_nocredit.png differ diff --git a/src/frontend/static/frontend/drawing_nocredit.svg b/src/frontend/static/frontend/drawing_nocredit.svg new file mode 100644 index 0000000..89c47fd --- /dev/null +++ b/src/frontend/static/frontend/drawing_nocredit.svg @@ -0,0 +1,818 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/frontend/drawing_nocredit_first-try-colors.png b/src/frontend/static/frontend/drawing_nocredit_first-try-colors.png new file mode 100644 index 0000000..18c9eb6 Binary files /dev/null and b/src/frontend/static/frontend/drawing_nocredit_first-try-colors.png differ diff --git a/src/frontend/static/frontend/drawing_nocredit_first-try-colors.svg b/src/frontend/static/frontend/drawing_nocredit_first-try-colors.svg new file mode 100644 index 0000000..b444133 --- /dev/null +++ b/src/frontend/static/frontend/drawing_nocredit_first-try-colors.svg @@ -0,0 +1,736 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/frontend/headers/drawing_nocredit.png b/src/frontend/static/frontend/headers/drawing_nocredit.png new file mode 100644 index 0000000..eff4549 Binary files /dev/null and b/src/frontend/static/frontend/headers/drawing_nocredit.png differ diff --git a/src/frontend/static/frontend/index/jumbotron.css b/src/frontend/static/frontend/index/jumbotron.css new file mode 100644 index 0000000..1f39637 --- /dev/null +++ b/src/frontend/static/frontend/index/jumbotron.css @@ -0,0 +1,7 @@ +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; + padding-bottom: 20px; +} + + diff --git a/src/frontend/static/frontend/index/styles.css b/src/frontend/static/frontend/index/styles.css new file mode 100644 index 0000000..5f64b70 --- /dev/null +++ b/src/frontend/static/frontend/index/styles.css @@ -0,0 +1,75 @@ +/* dynamic height based on width, for symbol header -------------------------*/ +#head-container { + display: inline-block; + position: relative; + width: 100%; +} +#dummy { + margin-top: 12.5%; /* 4:3 aspect ratio */ +} +#element { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: silver /* show me! */ +} + +/* navbar fixes -------------------------------------------------------------*/ +.navbar-inverse .navbar-toggle { + border-color: rgba(255, 255, 255, 0.2); +} + +.navbar-inverse .navbar-collapse, .navbar-default .navbar-form { + border-color: rgba(104, 104, 104, 0); +} + +.navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { + background-color: rgba(23, 23, 23, 0.44); +} + +.navbar-inverse .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { + background-color: rgba(0,0,0, 0.3); +} + + +/* cookie disclaimer fixes --------------------------------------------------*/ + +#CookielawBanner { + background-color: rgba(56, 60, 60, 0.73); + color: rgba(255,255,255, 0.5); + font-size: 1em; +} + + +#CookielawBanner .container { + width: 100% !important; +} + +#CookielawBanner h6 { + color: rgba(255,255,255, 0.8); + font-size: 1em; + font-weight: bold; + margin-bottom: 0; +} + + +/* Responsive overwrites ----------------------------------------------------*/ +/* Small devices (tablets, 768px and up) */ +@media (min-width: 768px) { } + +/* Medium devices (desktops, 992px and up) */ +@media (min-width: 992px) { + + .course-listing { + min-height: 220px; + } + +} + +/* Large devices (large desktops, 1200px and up) */ +@media (min-width: 1200px) { + + + } diff --git a/src/frontend/static/frontend/index/theme.css b/src/frontend/static/frontend/index/theme.css new file mode 100644 index 0000000..d238dc0 --- /dev/null +++ b/src/frontend/static/frontend/index/theme.css @@ -0,0 +1,7188 @@ +/*! Generated by Live LESS Theme Customizer */ + +@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700,400italic"); +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +div p a { + color: #337ab7; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot'); + src: url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff') format('woff'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #383c3c; + text-decoration: none; +} +a:hover, +a:focus { + color: #383c3c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 5px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #eeeeee; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1; + color: #333333; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #f1cc0f; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #999999; +} +.text-primary { + color: #383c3c; +} +a.text-primary:hover, +a.text-primary:focus { + color: #1f2222; +} +.text-success { + color: #ffffff; +} +a.text-success:hover, +a.text-success:focus { + color: #e6e6e6; +} +.text-info { + color: #ffffff; +} +a.text-info:hover, +a.text-info:focus { + color: #e6e6e6; +} +.text-warning { + color: #ffffff; +} +a.text-warning:hover, +a.text-warning:focus { + color: #e6e6e6; +} +.text-danger { + color: #ffffff; +} +a.text-danger:hover, +a.text-danger:focus { + color: #e6e6e6; +} +.bg-primary { + color: #fff; + background-color: #383c3c; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #1f2222; +} +.bg-success { + background-color: #55ff99; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #22ff7a; +} +.bg-info { + background-color: #55ddff; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #22d3ff; +} +.bg-warning { + background-color: #f1cc0f; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #c2a40b; +} +.bg-danger { + background-color: #ff2a7f; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #f60062; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 2px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #999999; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #eeeeee; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #eeeeee; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #eeeeee; +} +.table .table { + background-color: #ffffff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #eeeeee; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #eeeeee; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #55ff99; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #3bff8a; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #55ddff; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #3bd8ff; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #f1cc0f; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #dab80d; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #ff2a7f; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ff1170; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #eeeeee; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 8px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 38px; + padding: 7px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #e7e7e7; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eeeeee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 38px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 28px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 52px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 8px; + padding-bottom: 8px; + margin-bottom: 0; + min-height: 34px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +select.input-sm { + height: 28px; + line-height: 28px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.form-group-sm select.form-control { + height: 28px; + line-height: 28px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 28px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +select.input-lg { + height: 52px; + line-height: 52px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +.form-group-lg select.form-control { + height: 52px; + line-height: 52px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 52px; + min-height: 38px; + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 47.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 38px; + height: 38px; + line-height: 38px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 52px; + height: 52px; + line-height: 52px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 28px; + height: 28px; + line-height: 28px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #ffffff; +} +.has-success .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-success .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #55ff99; +} +.has-success .form-control-feedback { + color: #ffffff; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ffffff; +} +.has-warning .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-warning .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #f1cc0f; +} +.has-warning .form-control-feedback { + color: #ffffff; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #ffffff; +} +.has-error .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-error .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #ff2a7f; +} +.has-error .form-control-feedback { + color: #ffffff; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #959595; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 8px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 28px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 8px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 18.3333329px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 5px; + font-size: 12px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 7px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #555555; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #555555; + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-default:focus, +.btn-default.focus { + color: #555555; + background-color: #d5d5d5; + border-color: #a2a2a2; +} +.btn-default:hover { + color: #555555; + background-color: #d5d5d5; + border-color: #c3c3c3; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #555555; + background-color: #d5d5d5; + border-color: #c3c3c3; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #555555; + background-color: #c3c3c3; + border-color: #a2a2a2; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-default .badge { + color: #eeeeee; + background-color: #555555; +} +.btn-primary { + color: #ffffff; + background-color: #383c3c; + border-color: #2c2f2f; +} +.btn-primary:focus, +.btn-primary.focus { + color: #ffffff; + background-color: #1f2222; + border-color: #000000; +} +.btn-primary:hover { + color: #ffffff; + background-color: #1f2222; + border-color: #0e0f0f; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #1f2222; + border-color: #0e0f0f; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #ffffff; + background-color: #0e0f0f; + border-color: #000000; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #383c3c; + border-color: #2c2f2f; +} +.btn-primary .badge { + color: #383c3c; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5fd38d; + border-color: #4bcd7f; +} +.btn-success:focus, +.btn-success.focus { + color: #ffffff; + background-color: #37c870; + border-color: #217843; +} +.btn-success:hover { + color: #ffffff; + background-color: #37c870; + border-color: #2fac61; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #37c870; + border-color: #2fac61; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #ffffff; + background-color: #2fac61; + border-color: #217843; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5fd38d; + border-color: #4bcd7f; +} +.btn-success .badge { + color: #5fd38d; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #80b3ff; + border-color: #66a4ff; +} +.btn-info:focus, +.btn-info.focus { + color: #ffffff; + background-color: #4d94ff; + border-color: #005ce6; +} +.btn-info:hover { + color: #ffffff; + background-color: #4d94ff; + border-color: #297fff; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #4d94ff; + border-color: #297fff; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #ffffff; + background-color: #297fff; + border-color: #005ce6; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #80b3ff; + border-color: #66a4ff; +} +.btn-info .badge { + color: #80b3ff; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #ffdd55; + border-color: #ffd83b; +} +.btn-warning:focus, +.btn-warning.focus { + color: #ffffff; + background-color: #ffd322; + border-color: #bb9600; +} +.btn-warning:hover { + color: #ffffff; + background-color: #ffd322; + border-color: #fdcb00; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ffd322; + border-color: #fdcb00; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #ffffff; + background-color: #fdcb00; + border-color: #bb9600; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #ffdd55; + border-color: #ffd83b; +} +.btn-warning .badge { + color: #ffdd55; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #ff5599; + border-color: #ff3b8a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #ffffff; + background-color: #ff227a; + border-color: #bb004b; +} +.btn-danger:hover { + color: #ffffff; + background-color: #ff227a; + border-color: #fd0065; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #ff227a; + border-color: #fd0065; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #ffffff; + background-color: #fd0065; + border-color: #bb004b; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #ff5599; + border-color: #ff3b8a; +} +.btn-danger .badge { + color: #ff5599; + background-color: #ffffff; +} +.btn-link { + color: #383c3c; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #383c3c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid #e7e7e7; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #eeeeee; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #999999; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #333333; + background-color: transparent; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #383c3c; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #eeeeee; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999999; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 52px; + line-height: 52px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 28px; + line-height: 28px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 7px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #e7e7e7; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 4px 10px; + font-size: 12px; + border-radius: 2px; +} +.input-group-addon.input-lg { + padding: 13px 16px; + font-size: 18px; + border-radius: 5px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #ffffff; +} +.nav > li.disabled > a { + color: #999999; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #ffffff; + border-color: #383c3c; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #e7e7e7; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #e7e7e7; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #e7e7e7; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #e7e7e7; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #e7e7e7; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #383c3c; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #e7e7e7; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #e7e7e7; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 6px; + margin-bottom: 6px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 6px; + margin-bottom: 6px; +} +.navbar-btn.btn-sm { + margin-top: 11px; + margin-bottom: 11px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #8e8c8c; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #757272; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777777; +} +.navbar-default .navbar-nav > li > a { + color: #999999; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #8e8c8c; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #8e8c8c; + background-color: transparent; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #eeeeee; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ffffff; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #999999; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: transparent; + color: #8e8c8c; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #8e8c8c; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #8e8c8c; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #999999; +} +.navbar-default .navbar-link:hover { + color: #8e8c8c; +} +.navbar-default .btn-link { + color: #999999; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #8e8c8c; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #eeeeee; +} +.navbar-inverse { + background-color: #383c3c; + border-color: #1f2222; +} +.navbar-inverse .navbar-brand { + color: #999999; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #999999; +} +.navbar-inverse .navbar-nav > li > a { + color: #999999; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #1f2222; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #eeeeee; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #eeeeee; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #999999; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #272a2a; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #1f2222; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #1f2222; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #1f2222; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #1f2222; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #999999; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #999999; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #eeeeee; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #fafafa; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: ">\00a0"; + padding: 0 5px; + color: #999999; +} +.breadcrumb > .active { + color: #999999; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 7px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #555555; + background-color: #eeeeee; + border: 1px solid #e2e2e2; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 3; + color: #555555; + background-color: #eeeeee; + border-color: #e2e2e2; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #383c3c; + border-color: #2c2f2f; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #999999; + background-color: #eeeeee; + border-color: #e2e2e2; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 5px; + border-top-left-radius: 5px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #eeeeee; + border: 1px solid #e2e2e2; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + background-color: #eeeeee; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #999999; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #808080; +} +.label-primary { + background-color: #383c3c; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #1f2222; +} +.label-success { + background-color: #55ff99; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #22ff7a; +} +.label-info { + background-color: #55ddff; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #22d3ff; +} +.label-warning { + background-color: #f1cc0f; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #c2a40b; +} +.label-danger { + background-color: #ff2a7f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #f60062; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: normal; + color: #ffffff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #383c3c; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #383c3c; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #fafafa; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #e1e1e1; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 5px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #eeeeee; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #383c3c; +} +.thumbnail .caption { + padding: 9px; + color: #555555; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #5fd38d; + border-color: #37c870; + color: #ffffff; +} +.alert-success hr { + border-top-color: #32b465; +} +.alert-success .alert-link { + color: #e6e6e6; +} +.alert-info { + background-color: #5599ff; + border-color: #227aff; + color: #ffffff; +} +.alert-info hr { + border-top-color: #086bff; +} +.alert-info .alert-link { + color: #e6e6e6; +} +.alert-warning { + background-color: #f1cc0f; + border-color: #dab80d; + color: #ffffff; +} +.alert-warning hr { + border-top-color: #c2a40b; +} +.alert-warning .alert-link { + color: #e6e6e6; +} +.alert-danger { + background-color: #ff2a7f; + border-color: #f60062; + color: #ffffff; +} +.alert-danger hr { + border-top-color: #dd0058; +} +.alert-danger .alert-link { + color: #e6e6e6; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #fafafa; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #383c3c; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #55ff99; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #55ddff; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f1cc0f; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #ff2a7f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #eeeeee; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #999999; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #999999; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #383c3c; + border-color: #383c3c; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #9da3a3; +} +.list-group-item-success { + color: #ffffff; + background-color: #55ff99; +} +a.list-group-item-success, +button.list-group-item-success { + color: #ffffff; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #ffffff; + background-color: #3bff8a; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-info { + color: #ffffff; + background-color: #55ddff; +} +a.list-group-item-info, +button.list-group-item-info { + color: #ffffff; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #ffffff; + background-color: #3bd8ff; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-warning { + color: #ffffff; + background-color: #f1cc0f; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #ffffff; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #ffffff; + background-color: #dab80d; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-danger { + color: #ffffff; + background-color: #ff2a7f; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #ffffff; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #ffffff; + background-color: #ff1170; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid transparent; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #eeeeee; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid transparent; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid transparent; +} +.panel-default { + border-color: transparent; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: transparent; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-primary { + border-color: transparent; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #383c3c; + border-color: transparent; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-primary > .panel-heading .badge { + color: #383c3c; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-success { + border-color: transparent; +} +.panel-success > .panel-heading { + color: #ffffff; + background-color: #55ff99; + border-color: transparent; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-success > .panel-heading .badge { + color: #55ff99; + background-color: #ffffff; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-info { + border-color: transparent; +} +.panel-info > .panel-heading { + color: #ffffff; + background-color: #55ddff; + border-color: transparent; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-info > .panel-heading .badge { + color: #55ddff; + background-color: #ffffff; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-warning { + border-color: transparent; +} +.panel-warning > .panel-heading { + color: #ffffff; + background-color: #f1cc0f; + border-color: transparent; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-warning > .panel-heading .badge { + color: #f1cc0f; + background-color: #ffffff; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-danger { + border-color: transparent; +} +.panel-danger > .panel-heading { + color: #ffffff; + background-color: #ff2a7f; + border-color: transparent; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-danger > .panel-heading .badge { + color: #ff2a7f; + background-color: #ffffff; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #fafafa; + border: 1px solid #e8e8e8; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 5px; +} +.well-sm { + padding: 9px; + border-radius: 2px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #eeeeee; + border: 1px solid rgba(0, 0, 0, 0.05); + border-radius: 5px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + padding: 20px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 12px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 14px; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 4px 4px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + -moz-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +.navbar { + border-width: 0 1px 4px 1px; +} +.btn { + padding: 9px 12px 7px; + border-width: 0 1px 4px 1px; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; +} +.btn:hover { + margin-top: 1px; + border-bottom-width: 3px; +} +.btn:active { + margin-top: 2px; + border-bottom-width: 2px; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 15px 16px 13px; + line-height: 15px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 6px 10px 4px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 3px 5px 1px; +} +.btn-default:hover, +.btn-default:focus, +.btn-group.open .dropdown-toggle.btn-default { + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-group.open .dropdown-toggle.btn-primary { + background-color: #383c3c; + border-color: #2c2f2f; +} +.btn-success:hover, +.btn-success:focus, +.btn-group.open .dropdown-toggle.btn-success { + background-color: #5fd38d; + border-color: #4bcd7f; +} +.btn-info:hover, +.btn-info:focus, +.btn-group.open .dropdown-toggle.btn-info { + background-color: #80b3ff; + border-color: #66a4ff; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-group.open .dropdown-toggle.btn-warning { + background-color: #ffdd55; + border-color: #ffd83b; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-group.open .dropdown-toggle.btn-danger { + background-color: #ff5599; + border-color: #ff3b8a; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: none; + box-shadow: none; +} +.navbar-btn:hover { + margin-top: 8px; +} +.navbar-btn:active { + margin-top: 9px; +} +.navbar-btn.btn-sm:hover { + margin-top: 11px; +} +.navbar-btn.btn-sm:active { + margin-top: 12px; +} +.navbar-btn.btn-xs:hover { + margin-top: 15px; +} +.navbar-btn.btn-xs:active { + margin-top: 16px; +} +.btn-group-vertical .btn + .btn:hover { + border-top-width: 1px; +} +.btn-group-vertical .btn + .btn:active { + border-top-width: 2px; +} +.text-primary, +.text-primary:hover { + color: #383c3c; +} +.text-success, +.text-success:hover { + color: #55ff99; +} +.text-danger, +.text-danger:hover { + color: #ff2a7f; +} +.text-warning, +.text-warning:hover { + color: #f1cc0f; +} +.text-info, +.text-info:hover { + color: #55ddff; +} +table a:not(.btn), +.table a:not(.btn) { + text-decoration: underline; +} +table .dropdown-menu a, +.table .dropdown-menu a { + text-decoration: none; +} +table .success, +.table .success, +table .warning, +.table .warning, +table .danger, +.table .danger, +table .info, +.table .info { + color: #fff; +} +table .success a:not(.btn), +.table .success a:not(.btn), +table .warning a:not(.btn), +.table .warning a:not(.btn), +table .danger a:not(.btn), +.table .danger a:not(.btn), +table .info a:not(.btn), +.table .info a:not(.btn) { + color: #fff; +} +table:not(.table-bordered) > thead > tr > th, +.table:not(.table-bordered) > thead > tr > th, +table:not(.table-bordered) > tbody > tr > th, +.table:not(.table-bordered) > tbody > tr > th, +table:not(.table-bordered) > tfoot > tr > th, +.table:not(.table-bordered) > tfoot > tr > th, +table:not(.table-bordered) > thead > tr > td, +.table:not(.table-bordered) > thead > tr > td, +table:not(.table-bordered) > tbody > tr > td, +.table:not(.table-bordered) > tbody > tr > td, +table:not(.table-bordered) > tfoot > tr > td, +.table:not(.table-bordered) > tfoot > tr > td { + border-color: transparent; +} +.form-control { + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +label { + font-weight: normal; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label, +.has-warning .form-control-feedback { + color: #f1cc0f; +} +.has-warning .form-control, +.has-warning .form-control:focus { + border: 1px solid #f1cc0f; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-warning .input-group-addon { + border: 1px solid #f1cc0f; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label, +.has-error .form-control-feedback { + color: #ff2a7f; +} +.has-error .form-control, +.has-error .form-control:focus { + border: 1px solid #ff2a7f; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-error .input-group-addon { + border: 1px solid #ff2a7f; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label, +.has-success .form-control-feedback { + color: #55ff99; +} +.has-success .form-control, +.has-success .form-control:focus { + border: 1px solid #55ff99; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-success .input-group-addon { + border: 1px solid #55ff99; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + border-color: transparent; +} +.nav-tabs > li > a { + margin-top: 6px; + border-color: #e7e7e7; + color: #333333; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus, +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus, +.nav-tabs .open > a, +.nav-tabs .open > a:hover, +.nav-tabs .open > a:focus { + padding-bottom: 16px; + margin-top: 0; +} +.nav-tabs .open > a, +.nav-tabs .open > a:hover, +.nav-tabs .open > a:focus { + border-color: #e7e7e7; +} +.nav-tabs > li.disabled > a:hover, +.nav-tabs > li.disabled > a:focus { + padding-top: 10px; + padding-bottom: 10px; + margin-top: 6px; +} +.nav-tabs.nav-justified > li { + vertical-align: bottom; +} +.dropdown-menu { + margin-top: 0; + border-width: 0 1px 4px 1px; + border-top-width: 1px; + -webkit-box-shadow: none; + box-shadow: none; +} +.breadcrumb { + border-color: #ededed; + border-style: solid; + border-width: 0 1px 4px 1px; +} +.pagination > li > a, +.pager > li > a, +.pagination > li > span, +.pager > li > span { + position: relative; + top: 0; + border-width: 0 1px 4px 1px; + color: #555555; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; +} +.pagination > li > a:hover, +.pager > li > a:hover, +.pagination > li > span:hover, +.pager > li > span:hover { + top: 1px; + border-bottom-width: 3px; +} +.pagination > li > a:active, +.pager > li > a:active, +.pagination > li > span:active, +.pager > li > span:active { + top: 2px; + border-bottom-width: 2px; +} +.pagination > .disabled > a:hover, +.pager > .disabled > a:hover, +.pagination > .disabled > span:hover, +.pager > .disabled > span:hover { + top: 0; + border-width: 0 1px 4px 1px; +} +.pagination > .disabled > a:active, +.pager > .disabled > a:active, +.pagination > .disabled > span:active, +.pager > .disabled > span:active { + top: 0; + border-width: 0 1px 4px 1px; +} +.pager > li > a, +.pager > li > span, +.pager > .disabled > a, +.pager > .disabled > span, +.pager > li > a:hover, +.pager > li > span:hover, +.pager > .disabled > a:hover, +.pager > .disabled > span:hover, +.pager > li > a:active, +.pager > li > span:active, +.pager > .disabled > a:active, +.pager > .disabled > span:active { + border-left-width: 2px; + border-right-width: 2px; +} +.close { + color: #fff; + text-decoration: none; + opacity: 0.4; +} +.close:hover, +.close:focus { + color: #fff; + opacity: 1; +} +.alert { + border-width: 0 1px 4px 1px; +} +.alert .alert-link { + font-weight: normal; + color: #fff; + text-decoration: underline; +} +.label { + font-weight: normal; +} +.progress { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1); +} +.progress-bar { + -webkit-box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.15); +} +.well { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); +} +a.list-group-item.active, +a.list-group-item.active:hover, +a.list-group-item.active:focus { + border-color: #eeeeee; +} +a.list-group-item-success.active { + background-color: #55ff99; +} +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + background-color: #3bff8a; +} +a.list-group-item-warning.active { + background-color: #f1cc0f; +} +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + background-color: #dab80d; +} +a.list-group-item-danger.active { + background-color: #ff2a7f; +} +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + background-color: #ff1170; +} +.jumbotron { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); +} +.panel { + border: 1px solid #e7e7e7; + border-width: 0 1px 4px 1px; +} +.panel-default .close { + color: #555555; +} +.modal .close { + color: #555555; +} +.popover { + color: #555555; +} diff --git a/src/frontend/static/frontend/index/theme_lighter-component active.css b/src/frontend/static/frontend/index/theme_lighter-component active.css new file mode 100644 index 0000000..dd8caa0 --- /dev/null +++ b/src/frontend/static/frontend/index/theme_lighter-component active.css @@ -0,0 +1,7185 @@ +/*! Generated by Live LESS Theme Customizer */ + +@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700,400italic"); +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot'); + src: url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff') format('woff'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('http://bootstrap-live-customizer.com/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #525353; + text-decoration: none; +} +a:hover, +a:focus { + color: #525353; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 5px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #eeeeee; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1; + color: #333333; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #f1cc0f; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #999999; +} +.text-primary { + color: #525353; +} +a.text-primary:hover, +a.text-primary:focus { + color: #393939; +} +.text-success { + color: #ffffff; +} +a.text-success:hover, +a.text-success:focus { + color: #e6e6e6; +} +.text-info { + color: #ffffff; +} +a.text-info:hover, +a.text-info:focus { + color: #e6e6e6; +} +.text-warning { + color: #ffffff; +} +a.text-warning:hover, +a.text-warning:focus { + color: #e6e6e6; +} +.text-danger { + color: #ffffff; +} +a.text-danger:hover, +a.text-danger:focus { + color: #e6e6e6; +} +.bg-primary { + color: #fff; + background-color: #525353; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #393939; +} +.bg-success { + background-color: #62e261; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #37da36; +} +.bg-info { + background-color: #29c6e0; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #1ba4bb; +} +.bg-warning { + background-color: #f1cc0f; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #c2a40b; +} +.bg-danger { + background-color: #d94f6c; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #c92c4d; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 2px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #999999; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #eeeeee; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #eeeeee; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #eeeeee; +} +.table .table { + background-color: #ffffff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #eeeeee; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #eeeeee; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #62e261; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #4dde4b; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #29c6e0; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #1eb8d1; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #f1cc0f; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #dab80d; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #d94f6c; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #d43a5a; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #eeeeee; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 8px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 38px; + padding: 7px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #e7e7e7; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eeeeee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 38px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 28px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 52px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 8px; + padding-bottom: 8px; + margin-bottom: 0; + min-height: 34px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +select.input-sm { + height: 28px; + line-height: 28px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.form-group-sm select.form-control { + height: 28px; + line-height: 28px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 28px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +select.input-lg { + height: 52px; + line-height: 52px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +.form-group-lg select.form-control { + height: 52px; + line-height: 52px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 52px; + min-height: 38px; + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 47.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 38px; + height: 38px; + line-height: 38px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 52px; + height: 52px; + line-height: 52px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 28px; + height: 28px; + line-height: 28px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #ffffff; +} +.has-success .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-success .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #62e261; +} +.has-success .form-control-feedback { + color: #ffffff; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ffffff; +} +.has-warning .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-warning .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #f1cc0f; +} +.has-warning .form-control-feedback { + color: #ffffff; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #ffffff; +} +.has-error .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-error .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #d94f6c; +} +.has-error .form-control-feedback { + color: #ffffff; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #959595; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 8px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 28px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 8px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 18.3333329px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 5px; + font-size: 12px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 7px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #555555; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #555555; + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-default:focus, +.btn-default.focus { + color: #555555; + background-color: #d5d5d5; + border-color: #a2a2a2; +} +.btn-default:hover { + color: #555555; + background-color: #d5d5d5; + border-color: #c3c3c3; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #555555; + background-color: #d5d5d5; + border-color: #c3c3c3; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #555555; + background-color: #c3c3c3; + border-color: #a2a2a2; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-default .badge { + color: #eeeeee; + background-color: #555555; +} +.btn-primary { + color: #ffffff; + background-color: #525353; + border-color: #454646; +} +.btn-primary:focus, +.btn-primary.focus { + color: #ffffff; + background-color: #393939; + border-color: #060606; +} +.btn-primary:hover { + color: #ffffff; + background-color: #393939; + border-color: #272727; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #393939; + border-color: #272727; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #ffffff; + background-color: #272727; + border-color: #060606; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #525353; + border-color: #454646; +} +.btn-primary .badge { + color: #525353; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #62e261; + border-color: #4dde4b; +} +.btn-success:focus, +.btn-success.focus { + color: #ffffff; + background-color: #37da36; + border-color: #1b901a; +} +.btn-success:hover { + color: #ffffff; + background-color: #37da36; + border-color: #26c825; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #37da36; + border-color: #26c825; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #ffffff; + background-color: #26c825; + border-color: #1b901a; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #62e261; + border-color: #4dde4b; +} +.btn-success .badge { + color: #62e261; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #29c6e0; + border-color: #1eb8d1; +} +.btn-info:focus, +.btn-info.focus { + color: #ffffff; + background-color: #1ba4bb; + border-color: #0e5662; +} +.btn-info:hover { + color: #ffffff; + background-color: #1ba4bb; + border-color: #17899c; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #1ba4bb; + border-color: #17899c; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #ffffff; + background-color: #17899c; + border-color: #0e5662; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #29c6e0; + border-color: #1eb8d1; +} +.btn-info .badge { + color: #29c6e0; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f1cc0f; + border-color: #dab80d; +} +.btn-warning:focus, +.btn-warning.focus { + color: #ffffff; + background-color: #c2a40b; + border-color: #615206; +} +.btn-warning:hover { + color: #ffffff; + background-color: #c2a40b; + border-color: #a08709; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #c2a40b; + border-color: #a08709; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #ffffff; + background-color: #a08709; + border-color: #615206; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f1cc0f; + border-color: #dab80d; +} +.btn-warning .badge { + color: #f1cc0f; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d94f6c; + border-color: #d43a5a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #ffffff; + background-color: #c92c4d; + border-color: #76192d; +} +.btn-danger:hover { + color: #ffffff; + background-color: #c92c4d; + border-color: #ac2542; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c92c4d; + border-color: #ac2542; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #ffffff; + background-color: #ac2542; + border-color: #76192d; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d94f6c; + border-color: #d43a5a; +} +.btn-danger .badge { + color: #d94f6c; + background-color: #ffffff; +} +.btn-link { + color: #525353; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #525353; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid #e7e7e7; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #eeeeee; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #999999; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #333333; + background-color: transparent; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #525353; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #eeeeee; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999999; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 52px; + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 5px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 52px; + line-height: 52px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 28px; + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 2px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 28px; + line-height: 28px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 7px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #e7e7e7; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 4px 10px; + font-size: 12px; + border-radius: 2px; +} +.input-group-addon.input-lg { + padding: 13px 16px; + font-size: 18px; + border-radius: 5px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #ffffff; +} +.nav > li.disabled > a { + color: #999999; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #ffffff; + border-color: #525353; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #e7e7e7; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #e7e7e7; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #e7e7e7; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #e7e7e7; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #e7e7e7; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #525353; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #e7e7e7; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #e7e7e7; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 6px; + margin-bottom: 6px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 6px; + margin-bottom: 6px; +} +.navbar-btn.btn-sm { + margin-top: 11px; + margin-bottom: 11px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #353535; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #8e8c8c; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #8e8c8c; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #d8d3d3; +} +.navbar-default .navbar-nav > li > a { + color: #999999; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #8e8c8c; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #8e8c8c; + background-color: transparent; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #eeeeee; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ffffff; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #999999; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: transparent; + color: #8e8c8c; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #8e8c8c; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #8e8c8c; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #999999; +} +.navbar-default .navbar-link:hover { + color: #8e8c8c; +} +.navbar-default .btn-link { + color: #999999; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #8e8c8c; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #eeeeee; +} +.navbar-inverse { + background-color: #ffffff; + border-color: #e6e6e6; +} +.navbar-inverse .navbar-brand { + color: #ffffff; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #333333; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #999999; +} +.navbar-inverse .navbar-nav > li > a { + color: #999999; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #333333; + background-color: #89be3d; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #eeeeee; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #eeeeee; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #999999; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #ededed; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #89be3d; + color: #333333; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #e6e6e6; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #e6e6e6; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #333333; + background-color: #89be3d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #eeeeee; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #999999; +} +.navbar-inverse .navbar-link:hover { + color: #333333; +} +.navbar-inverse .btn-link { + color: #999999; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #333333; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #eeeeee; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #fafafa; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: ">\00a0"; + padding: 0 5px; + color: #999999; +} +.breadcrumb > .active { + color: #999999; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 7px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #555555; + background-color: #eeeeee; + border: 1px solid #e2e2e2; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 3; + color: #555555; + background-color: #eeeeee; + border-color: #e2e2e2; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #525353; + border-color: #454646; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #999999; + background-color: #eeeeee; + border-color: #e2e2e2; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 13px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 5px; + border-top-left-radius: 5px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 4px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #eeeeee; + border: 1px solid #e2e2e2; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + background-color: #eeeeee; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #999999; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #808080; +} +.label-primary { + background-color: #525353; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #393939; +} +.label-success { + background-color: #62e261; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #37da36; +} +.label-info { + background-color: #29c6e0; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #1ba4bb; +} +.label-warning { + background-color: #f1cc0f; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #c2a40b; +} +.label-danger { + background-color: #d94f6c; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c92c4d; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: normal; + color: #ffffff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #525353; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #525353; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #fafafa; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #e1e1e1; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 5px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #eeeeee; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #525353; +} +.thumbnail .caption { + padding: 9px; + color: #555555; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #62e261; + border-color: #51df50; + color: #ffffff; +} +.alert-success hr { + border-top-color: #3bdb3a; +} +.alert-success .alert-link { + color: #e6e6e6; +} +.alert-info { + background-color: #29c6e0; + border-color: #1a9cb2; + color: #ffffff; +} +.alert-info hr { + border-top-color: #17899c; +} +.alert-info .alert-link { + color: #e6e6e6; +} +.alert-warning { + background-color: #f1cc0f; + border-color: #dab80d; + color: #ffffff; +} +.alert-warning hr { + border-top-color: #c2a40b; +} +.alert-warning .alert-link { + color: #e6e6e6; +} +.alert-danger { + background-color: #d94f6c; + border-color: #c92c4d; + color: #ffffff; +} +.alert-danger hr { + border-top-color: #b52745; +} +.alert-danger .alert-link { + color: #e6e6e6; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #fafafa; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #525353; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #62e261; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #29c6e0; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f1cc0f; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d94f6c; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #eeeeee; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #999999; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #999999; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #525353; + border-color: #525353; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #b8b9b9; +} +.list-group-item-success { + color: #ffffff; + background-color: #62e261; +} +a.list-group-item-success, +button.list-group-item-success { + color: #ffffff; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #ffffff; + background-color: #4dde4b; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-info { + color: #ffffff; + background-color: #29c6e0; +} +a.list-group-item-info, +button.list-group-item-info { + color: #ffffff; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #ffffff; + background-color: #1eb8d1; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-warning { + color: #ffffff; + background-color: #f1cc0f; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #ffffff; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #ffffff; + background-color: #dab80d; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-danger { + color: #ffffff; + background-color: #d94f6c; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #ffffff; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #ffffff; + background-color: #d43a5a; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid transparent; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #eeeeee; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid transparent; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid transparent; +} +.panel-default { + border-color: transparent; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: transparent; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-primary { + border-color: transparent; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #525353; + border-color: transparent; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-primary > .panel-heading .badge { + color: #525353; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-success { + border-color: transparent; +} +.panel-success > .panel-heading { + color: #ffffff; + background-color: #62e261; + border-color: transparent; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-success > .panel-heading .badge { + color: #62e261; + background-color: #ffffff; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-info { + border-color: transparent; +} +.panel-info > .panel-heading { + color: #ffffff; + background-color: #29c6e0; + border-color: transparent; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-info > .panel-heading .badge { + color: #29c6e0; + background-color: #ffffff; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-warning { + border-color: transparent; +} +.panel-warning > .panel-heading { + color: #ffffff; + background-color: #f1cc0f; + border-color: transparent; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-warning > .panel-heading .badge { + color: #f1cc0f; + background-color: #ffffff; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.panel-danger { + border-color: transparent; +} +.panel-danger > .panel-heading { + color: #ffffff; + background-color: #d94f6c; + border-color: transparent; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: transparent; +} +.panel-danger > .panel-heading .badge { + color: #d94f6c; + background-color: #ffffff; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: transparent; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #fafafa; + border: 1px solid #e8e8e8; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 5px; +} +.well-sm { + padding: 9px; + border-radius: 2px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #eeeeee; + border: 1px solid rgba(0, 0, 0, 0.05); + border-radius: 5px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + padding: 20px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 12px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 14px; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 4px 4px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + -moz-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +.navbar { + border-width: 0 1px 4px 1px; +} +.btn { + padding: 9px 12px 7px; + border-width: 0 1px 4px 1px; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; +} +.btn:hover { + margin-top: 1px; + border-bottom-width: 3px; +} +.btn:active { + margin-top: 2px; + border-bottom-width: 2px; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 15px 16px 13px; + line-height: 15px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 6px 10px 4px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 3px 5px 1px; +} +.btn-default:hover, +.btn-default:focus, +.btn-group.open .dropdown-toggle.btn-default { + background-color: #eeeeee; + border-color: #e2e2e2; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-group.open .dropdown-toggle.btn-primary { + background-color: #525353; + border-color: #454646; +} +.btn-success:hover, +.btn-success:focus, +.btn-group.open .dropdown-toggle.btn-success { + background-color: #62e261; + border-color: #4dde4b; +} +.btn-info:hover, +.btn-info:focus, +.btn-group.open .dropdown-toggle.btn-info { + background-color: #29c6e0; + border-color: #1eb8d1; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-group.open .dropdown-toggle.btn-warning { + background-color: #f1cc0f; + border-color: #dab80d; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-group.open .dropdown-toggle.btn-danger { + background-color: #d94f6c; + border-color: #d43a5a; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: none; + box-shadow: none; +} +.navbar-btn:hover { + margin-top: 8px; +} +.navbar-btn:active { + margin-top: 9px; +} +.navbar-btn.btn-sm:hover { + margin-top: 11px; +} +.navbar-btn.btn-sm:active { + margin-top: 12px; +} +.navbar-btn.btn-xs:hover { + margin-top: 15px; +} +.navbar-btn.btn-xs:active { + margin-top: 16px; +} +.btn-group-vertical .btn + .btn:hover { + border-top-width: 1px; +} +.btn-group-vertical .btn + .btn:active { + border-top-width: 2px; +} +.text-primary, +.text-primary:hover { + color: #525353; +} +.text-success, +.text-success:hover { + color: #62e261; +} +.text-danger, +.text-danger:hover { + color: #d94f6c; +} +.text-warning, +.text-warning:hover { + color: #f1cc0f; +} +.text-info, +.text-info:hover { + color: #29c6e0; +} +table a:not(.btn), +.table a:not(.btn) { + text-decoration: underline; +} +table .dropdown-menu a, +.table .dropdown-menu a { + text-decoration: none; +} +table .success, +.table .success, +table .warning, +.table .warning, +table .danger, +.table .danger, +table .info, +.table .info { + color: #fff; +} +table .success a:not(.btn), +.table .success a:not(.btn), +table .warning a:not(.btn), +.table .warning a:not(.btn), +table .danger a:not(.btn), +.table .danger a:not(.btn), +table .info a:not(.btn), +.table .info a:not(.btn) { + color: #fff; +} +table:not(.table-bordered) > thead > tr > th, +.table:not(.table-bordered) > thead > tr > th, +table:not(.table-bordered) > tbody > tr > th, +.table:not(.table-bordered) > tbody > tr > th, +table:not(.table-bordered) > tfoot > tr > th, +.table:not(.table-bordered) > tfoot > tr > th, +table:not(.table-bordered) > thead > tr > td, +.table:not(.table-bordered) > thead > tr > td, +table:not(.table-bordered) > tbody > tr > td, +.table:not(.table-bordered) > tbody > tr > td, +table:not(.table-bordered) > tfoot > tr > td, +.table:not(.table-bordered) > tfoot > tr > td { + border-color: transparent; +} +.form-control { + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +label { + font-weight: normal; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label, +.has-warning .form-control-feedback { + color: #f1cc0f; +} +.has-warning .form-control, +.has-warning .form-control:focus { + border: 1px solid #f1cc0f; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-warning .input-group-addon { + border: 1px solid #f1cc0f; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label, +.has-error .form-control-feedback { + color: #d94f6c; +} +.has-error .form-control, +.has-error .form-control:focus { + border: 1px solid #d94f6c; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-error .input-group-addon { + border: 1px solid #d94f6c; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label, +.has-success .form-control-feedback { + color: #62e261; +} +.has-success .form-control, +.has-success .form-control:focus { + border: 1px solid #62e261; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); +} +.has-success .input-group-addon { + border: 1px solid #62e261; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + border-color: transparent; +} +.nav-tabs > li > a { + margin-top: 6px; + border-color: #e7e7e7; + color: #333333; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus, +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus, +.nav-tabs .open > a, +.nav-tabs .open > a:hover, +.nav-tabs .open > a:focus { + padding-bottom: 16px; + margin-top: 0; +} +.nav-tabs .open > a, +.nav-tabs .open > a:hover, +.nav-tabs .open > a:focus { + border-color: #e7e7e7; +} +.nav-tabs > li.disabled > a:hover, +.nav-tabs > li.disabled > a:focus { + padding-top: 10px; + padding-bottom: 10px; + margin-top: 6px; +} +.nav-tabs.nav-justified > li { + vertical-align: bottom; +} +.dropdown-menu { + margin-top: 0; + border-width: 0 1px 4px 1px; + border-top-width: 1px; + -webkit-box-shadow: none; + box-shadow: none; +} +.breadcrumb { + border-color: #ededed; + border-style: solid; + border-width: 0 1px 4px 1px; +} +.pagination > li > a, +.pager > li > a, +.pagination > li > span, +.pager > li > span { + position: relative; + top: 0; + border-width: 0 1px 4px 1px; + color: #555555; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; +} +.pagination > li > a:hover, +.pager > li > a:hover, +.pagination > li > span:hover, +.pager > li > span:hover { + top: 1px; + border-bottom-width: 3px; +} +.pagination > li > a:active, +.pager > li > a:active, +.pagination > li > span:active, +.pager > li > span:active { + top: 2px; + border-bottom-width: 2px; +} +.pagination > .disabled > a:hover, +.pager > .disabled > a:hover, +.pagination > .disabled > span:hover, +.pager > .disabled > span:hover { + top: 0; + border-width: 0 1px 4px 1px; +} +.pagination > .disabled > a:active, +.pager > .disabled > a:active, +.pagination > .disabled > span:active, +.pager > .disabled > span:active { + top: 0; + border-width: 0 1px 4px 1px; +} +.pager > li > a, +.pager > li > span, +.pager > .disabled > a, +.pager > .disabled > span, +.pager > li > a:hover, +.pager > li > span:hover, +.pager > .disabled > a:hover, +.pager > .disabled > span:hover, +.pager > li > a:active, +.pager > li > span:active, +.pager > .disabled > a:active, +.pager > .disabled > span:active { + border-left-width: 2px; + border-right-width: 2px; +} +.close { + color: #fff; + text-decoration: none; + opacity: 0.4; +} +.close:hover, +.close:focus { + color: #fff; + opacity: 1; +} +.alert { + border-width: 0 1px 4px 1px; +} +.alert .alert-link { + font-weight: normal; + color: #fff; + text-decoration: underline; +} +.label { + font-weight: normal; +} +.progress { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1); +} +.progress-bar { + -webkit-box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.15); +} +.well { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); +} +a.list-group-item.active, +a.list-group-item.active:hover, +a.list-group-item.active:focus { + border-color: #eeeeee; +} +a.list-group-item-success.active { + background-color: #62e261; +} +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + background-color: #4dde4b; +} +a.list-group-item-warning.active { + background-color: #f1cc0f; +} +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + background-color: #dab80d; +} +a.list-group-item-danger.active { + background-color: #d94f6c; +} +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + background-color: #d43a5a; +} +.jumbotron { + border: 1px solid #e7e7e7; + -webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.05); +} +.panel { + border: 1px solid #e7e7e7; + border-width: 0 1px 4px 1px; +} +.panel-default .close { + color: #555555; +} +.modal .close { + color: #555555; +} +.popover { + color: #555555; +} diff --git a/src/frontend/static/frontend/settings/dashboard.css b/src/frontend/static/frontend/settings/dashboard.css new file mode 100644 index 0000000..e0e3632 --- /dev/null +++ b/src/frontend/static/frontend/settings/dashboard.css @@ -0,0 +1,105 @@ +/* + * Base structure + */ + +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; +} + + +/* + * Global add-ons + */ + +.sub-header { + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +/* + * Top navigation + * Hide default border to remove 1px line. + */ +.navbar-fixed-top { + border: 0; +} + +/* + * Sidebar + */ + +/* Hide for mobile, show later */ +.sidebar { + display: none; +} +@media (min-width: 768px) { + .sidebar { + position: fixed; + top: 51px; + bottom: 0; + left: 0; + z-index: 1000; + display: block; + padding: 20px; + overflow-x: hidden; + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + background-color: #f5f5f5; + border-right: 1px solid #eee; + } +} + +/* Sidebar navigation */ +.nav-sidebar { + margin-right: -21px; /* 20px padding + 1px border */ + margin-bottom: 20px; + margin-left: -20px; +} +.nav-sidebar > li > a { + padding-right: 20px; + padding-left: 20px; +} +.nav-sidebar > .active > a, +.nav-sidebar > .active > a:hover, +.nav-sidebar > .active > a:focus { + color: #fff; + background-color: #428bca; +} + + +/* + * Main content + */ + +.main { + padding: 20px; +} +@media (min-width: 768px) { + .main { + padding-right: 40px; + padding-left: 40px; + } +} +.main .page-header { + margin-top: 0; +} + + +/* + * Placeholder dashboard ideas + */ + +.placeholders { + margin-bottom: 30px; + text-align: center; +} +.placeholders h4 { + margin-bottom: 0; +} +.placeholder { + margin-bottom: 20px; +} +.placeholder img { + display: inline-block; + border-radius: 50%; +} diff --git a/src/frontend/static/lib/backbone-min.js b/src/frontend/static/lib/backbone-min.js new file mode 100644 index 0000000..1a1f708 --- /dev/null +++ b/src/frontend/static/lib/backbone-min.js @@ -0,0 +1,2 @@ +(function(t){var e=typeof self=="object"&&self.self==self&&self||typeof global=="object"&&global.global==global&&global;if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,n){e.Backbone=t(e,n,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore"),r;try{r=require("jquery")}catch(n){}t(e,exports,i,r)}else{e.Backbone=t(e,{},e._,e.jQuery||e.Zepto||e.ender||e.$)}})(function(t,e,i,r){var n=t.Backbone;var s=Array.prototype.slice;e.VERSION="1.2.3";e.$=r;e.noConflict=function(){t.Backbone=n;return this};e.emulateHTTP=false;e.emulateJSON=false;var a=function(t,e,r){switch(t){case 1:return function(){return i[e](this[r])};case 2:return function(t){return i[e](this[r],t)};case 3:return function(t,n){return i[e](this[r],h(t,this),n)};case 4:return function(t,n,s){return i[e](this[r],h(t,this),n,s)};default:return function(){var t=s.call(arguments);t.unshift(this[r]);return i[e].apply(i,t)}}};var o=function(t,e,r){i.each(e,function(e,n){if(i[n])t.prototype[n]=a(e,n,r)})};var h=function(t,e){if(i.isFunction(t))return t;if(i.isObject(t)&&!e._isModel(t))return u(t);if(i.isString(t))return function(e){return e.get(t)};return t};var u=function(t){var e=i.matches(t);return function(t){return e(t.attributes)}};var l=e.Events={};var c=/\s+/;var f=function(t,e,r,n,s){var a=0,o;if(r&&typeof r==="object"){if(n!==void 0&&"context"in s&&s.context===void 0)s.context=n;for(o=i.keys(r);a7);this._useHashChange=this._wantsHashChange&&this._hasHashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.history&&this.history.pushState);this._usePushState=this._wantsPushState&&this._hasPushState;this.fragment=this.getFragment();this.root=("/"+this.root+"/").replace(O,"/");if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!this.atRoot()){var e=this.root.slice(0,-1)||"/";this.location.replace(e+"#"+this.getPath());return true}else if(this._hasPushState&&this.atRoot()){this.navigate(this.getHash(),{replace:true})}}if(!this._hasHashChange&&this._wantsHashChange&&!this._usePushState){this.iframe=document.createElement("iframe");this.iframe.src="javascript:0";this.iframe.style.display="none";this.iframe.tabIndex=-1;var r=document.body;var n=r.insertBefore(this.iframe,r.firstChild).contentWindow;n.document.open();n.document.close();n.location.hash="#"+this.fragment}var s=window.addEventListener||function(t,e){return attachEvent("on"+t,e)};if(this._usePushState){s("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){s("hashchange",this.checkUrl,false)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}if(!this.options.silent)return this.loadUrl()},stop:function(){var t=window.removeEventListener||function(t,e){return detachEvent("on"+t,e)};if(this._usePushState){t("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){t("hashchange",this.checkUrl,false)}if(this.iframe){document.body.removeChild(this.iframe);this.iframe=null}if(this._checkUrlInterval)clearInterval(this._checkUrlInterval);M.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getHash(this.iframe.contentWindow)}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()},loadUrl:function(t){if(!this.matchRoot())return false;t=this.fragment=this.getFragment(t);return i.some(this.handlers,function(e){if(e.route.test(t)){e.callback(t);return true}})},navigate:function(t,e){if(!M.started)return false;if(!e||e===true)e={trigger:!!e};t=this.getFragment(t||"");var i=this.root;if(t===""||t.charAt(0)==="?"){i=i.slice(0,-1)||"/"}var r=i+t;t=this.decodeFragment(t.replace(U,""));if(this.fragment===t)return;this.fragment=t;if(this._usePushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,r)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getHash(this.iframe.contentWindow)){var n=this.iframe.contentWindow;if(!e.replace){n.document.open();n.document.close()}this._updateHash(n.location,t,e.replace)}}else{return this.location.assign(r)}if(e.trigger)return this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});e.history=new M;var q=function(t,e){var r=this;var n;if(t&&i.has(t,"constructor")){n=t.constructor}else{n=function(){return r.apply(this,arguments)}}i.extend(n,r,e);var s=function(){this.constructor=n};s.prototype=r.prototype;n.prototype=new s;if(t)i.extend(n.prototype,t);n.__super__=r.prototype;return n};y.extend=x.extend=$.extend=I.extend=M.extend=q;var F=function(){throw new Error('A "url" property or function must be specified')};var z=function(t,e){var i=e.error;e.error=function(r){if(i)i.call(e.context,t,r,e);t.trigger("error",t,r,e)}};return e}); +//# sourceMappingURL=backbone-min.map \ No newline at end of file diff --git a/src/frontend/static/lib/backbone.js b/src/frontend/static/lib/backbone.js new file mode 100644 index 0000000..c924965 --- /dev/null +++ b/src/frontend/static/lib/backbone.js @@ -0,0 +1,1894 @@ +// Backbone.js 1.2.3 + +// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org + +(function(factory) { + + // Establish the root object, `window` (`self`) in the browser, or `global` on the server. + // We use `self` instead of `window` for `WebWorker` support. + var root = (typeof self == 'object' && self.self == self && self) || + (typeof global == 'object' && global.global == global && global); + + // Set up Backbone appropriately for the environment. Start with AMD. + if (typeof define === 'function' && define.amd) { + define(['underscore', 'jquery', 'exports'], function(_, $, exports) { + // Export global even in AMD case in case this script is loaded with + // others that may still expect a global Backbone. + root.Backbone = factory(root, exports, _, $); + }); + + // Next for Node.js or CommonJS. jQuery may not be needed as a module. + } else if (typeof exports !== 'undefined') { + var _ = require('underscore'), $; + try { $ = require('jquery'); } catch(e) {} + factory(root, exports, _, $); + + // Finally, as a browser global. + } else { + root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$)); + } + +}(function(root, Backbone, _, $) { + + // Initial Setup + // ------------- + + // Save the previous value of the `Backbone` variable, so that it can be + // restored later on, if `noConflict` is used. + var previousBackbone = root.Backbone; + + // Create a local reference to a common array method we'll want to use later. + var slice = Array.prototype.slice; + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '1.2.3'; + + // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns + // the `$` variable. + Backbone.$ = $; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function() { + root.Backbone = previousBackbone; + return this; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option + // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and + // set a `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... this will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Proxy Backbone class methods to Underscore functions, wrapping the model's + // `attributes` object or collection's `models` array behind the scenes. + // + // collection.filter(function(model) { return model.get('age') > 10 }); + // collection.each(this.addView); + // + // `Function#apply` can be slow so we use the method's arg count, if we know it. + var addMethod = function(length, method, attribute) { + switch (length) { + case 1: return function() { + return _[method](this[attribute]); + }; + case 2: return function(value) { + return _[method](this[attribute], value); + }; + case 3: return function(iteratee, context) { + return _[method](this[attribute], cb(iteratee, this), context); + }; + case 4: return function(iteratee, defaultVal, context) { + return _[method](this[attribute], cb(iteratee, this), defaultVal, context); + }; + default: return function() { + var args = slice.call(arguments); + args.unshift(this[attribute]); + return _[method].apply(_, args); + }; + } + }; + var addUnderscoreMethods = function(Class, methods, attribute) { + _.each(methods, function(length, method) { + if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); + }); + }; + + // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`. + var cb = function(iteratee, instance) { + if (_.isFunction(iteratee)) return iteratee; + if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee); + if (_.isString(iteratee)) return function(model) { return model.get(iteratee); }; + return iteratee; + }; + var modelMatcher = function(attrs) { + var matcher = _.matches(attrs); + return function(model) { + return matcher(model.attributes); + }; + }; + + // Backbone.Events + // --------------- + + // A module that can be mixed in to *any object* in order to provide it with + // a custom event channel. You may bind a callback to an event with `on` or + // remove with `off`; `trigger`-ing an event fires all callbacks in + // succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.on('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + var Events = Backbone.Events = {}; + + // Regular expression used to split event strings. + var eventSplitter = /\s+/; + + // Iterates over the standard `event, callback` (as well as the fancy multiple + // space-separated events `"change blur", callback` and jQuery-style event + // maps `{event: callback}`). + var eventsApi = function(iteratee, events, name, callback, opts) { + var i = 0, names; + if (name && typeof name === 'object') { + // Handle event maps. + if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; + for (names = _.keys(name); i < names.length ; i++) { + events = eventsApi(iteratee, events, names[i], name[names[i]], opts); + } + } else if (name && eventSplitter.test(name)) { + // Handle space separated event names by delegating them individually. + for (names = name.split(eventSplitter); i < names.length; i++) { + events = iteratee(events, names[i], callback, opts); + } + } else { + // Finally, standard events. + events = iteratee(events, name, callback, opts); + } + return events; + }; + + // Bind an event to a `callback` function. Passing `"all"` will bind + // the callback to all events fired. + Events.on = function(name, callback, context) { + return internalOn(this, name, callback, context); + }; + + // Guard the `listening` argument from the public API. + var internalOn = function(obj, name, callback, context, listening) { + obj._events = eventsApi(onApi, obj._events || {}, name, callback, { + context: context, + ctx: obj, + listening: listening + }); + + if (listening) { + var listeners = obj._listeners || (obj._listeners = {}); + listeners[listening.id] = listening; + } + + return obj; + }; + + // Inversion-of-control versions of `on`. Tell *this* object to listen to + // an event in another object... keeping track of what it's listening to + // for easier unbinding later. + Events.listenTo = function(obj, name, callback) { + if (!obj) return this; + var id = obj._listenId || (obj._listenId = _.uniqueId('l')); + var listeningTo = this._listeningTo || (this._listeningTo = {}); + var listening = listeningTo[id]; + + // This object is not listening to any other events on `obj` yet. + // Setup the necessary references to track the listening callbacks. + if (!listening) { + var thisId = this._listenId || (this._listenId = _.uniqueId('l')); + listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0}; + } + + // Bind callbacks on obj, and keep track of them on listening. + internalOn(obj, name, callback, this, listening); + return this; + }; + + // The reducing API that adds a callback to the `events` object. + var onApi = function(events, name, callback, options) { + if (callback) { + var handlers = events[name] || (events[name] = []); + var context = options.context, ctx = options.ctx, listening = options.listening; + if (listening) listening.count++; + + handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening }); + } + return events; + }; + + // Remove one or many callbacks. If `context` is null, removes all + // callbacks with that function. If `callback` is null, removes all + // callbacks for the event. If `name` is null, removes all bound + // callbacks for all events. + Events.off = function(name, callback, context) { + if (!this._events) return this; + this._events = eventsApi(offApi, this._events, name, callback, { + context: context, + listeners: this._listeners + }); + return this; + }; + + // Tell this object to stop listening to either specific events ... or + // to every object it's currently listening to. + Events.stopListening = function(obj, name, callback) { + var listeningTo = this._listeningTo; + if (!listeningTo) return this; + + var ids = obj ? [obj._listenId] : _.keys(listeningTo); + + for (var i = 0; i < ids.length; i++) { + var listening = listeningTo[ids[i]]; + + // If listening doesn't exist, this object is not currently + // listening to obj. Break out early. + if (!listening) break; + + listening.obj.off(name, callback, this); + } + if (_.isEmpty(listeningTo)) this._listeningTo = void 0; + + return this; + }; + + // The reducing API that removes a callback from the `events` object. + var offApi = function(events, name, callback, options) { + if (!events) return; + + var i = 0, listening; + var context = options.context, listeners = options.listeners; + + // Delete all events listeners and "drop" events. + if (!name && !callback && !context) { + var ids = _.keys(listeners); + for (; i < ids.length; i++) { + listening = listeners[ids[i]]; + delete listeners[listening.id]; + delete listening.listeningTo[listening.objId]; + } + return; + } + + var names = name ? [name] : _.keys(events); + for (; i < names.length; i++) { + name = names[i]; + var handlers = events[name]; + + // Bail out if there are no events stored. + if (!handlers) break; + + // Replace events if there are any remaining. Otherwise, clean up. + var remaining = []; + for (var j = 0; j < handlers.length; j++) { + var handler = handlers[j]; + if ( + callback && callback !== handler.callback && + callback !== handler.callback._callback || + context && context !== handler.context + ) { + remaining.push(handler); + } else { + listening = handler.listening; + if (listening && --listening.count === 0) { + delete listeners[listening.id]; + delete listening.listeningTo[listening.objId]; + } + } + } + + // Update tail event if the list has any events. Otherwise, clean up. + if (remaining.length) { + events[name] = remaining; + } else { + delete events[name]; + } + } + if (_.size(events)) return events; + }; + + // Bind an event to only be triggered a single time. After the first time + // the callback is invoked, its listener will be removed. If multiple events + // are passed in using the space-separated syntax, the handler will fire + // once for each event, not once for a combination of all events. + Events.once = function(name, callback, context) { + // Map the event into a `{event: once}` object. + var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this)); + return this.on(events, void 0, context); + }; + + // Inversion-of-control versions of `once`. + Events.listenToOnce = function(obj, name, callback) { + // Map the event into a `{event: once}` object. + var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj)); + return this.listenTo(obj, events); + }; + + // Reduces the event callbacks into a map of `{event: onceWrapper}`. + // `offer` unbinds the `onceWrapper` after it has been called. + var onceMap = function(map, name, callback, offer) { + if (callback) { + var once = map[name] = _.once(function() { + offer(name, once); + callback.apply(this, arguments); + }); + once._callback = callback; + } + return map; + }; + + // Trigger one or many events, firing all bound callbacks. Callbacks are + // passed the same arguments as `trigger` is, apart from the event name + // (unless you're listening on `"all"`, which will cause your callback to + // receive the true name of the event as the first argument). + Events.trigger = function(name) { + if (!this._events) return this; + + var length = Math.max(0, arguments.length - 1); + var args = Array(length); + for (var i = 0; i < length; i++) args[i] = arguments[i + 1]; + + eventsApi(triggerApi, this._events, name, void 0, args); + return this; + }; + + // Handles triggering the appropriate event callbacks. + var triggerApi = function(objEvents, name, cb, args) { + if (objEvents) { + var events = objEvents[name]; + var allEvents = objEvents.all; + if (events && allEvents) allEvents = allEvents.slice(); + if (events) triggerEvents(events, args); + if (allEvents) triggerEvents(allEvents, [name].concat(args)); + } + return objEvents; + }; + + // A difficult-to-believe, but optimized internal dispatch function for + // triggering events. Tries to keep the usual cases speedy (most internal + // Backbone events have 3 arguments). + var triggerEvents = function(events, args) { + var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; + switch (args.length) { + case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; + case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; + case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; + case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; + default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; + } + }; + + // Aliases for backwards compatibility. + Events.bind = Events.on; + Events.unbind = Events.off; + + // Allow the `Backbone` object to serve as a global event bus, for folks who + // want global "pubsub" in a convenient place. + _.extend(Backbone, Events); + + // Backbone.Model + // -------------- + + // Backbone **Models** are the basic data object in the framework -- + // frequently representing a row in a table in a database on your server. + // A discrete chunk of data and a bunch of useful, related methods for + // performing computations and transformations on that data. + + // Create a new model with the specified attributes. A client id (`cid`) + // is automatically generated and assigned for you. + var Model = Backbone.Model = function(attributes, options) { + var attrs = attributes || {}; + options || (options = {}); + this.cid = _.uniqueId(this.cidPrefix); + this.attributes = {}; + if (options.collection) this.collection = options.collection; + if (options.parse) attrs = this.parse(attrs, options) || {}; + attrs = _.defaults({}, attrs, _.result(this, 'defaults')); + this.set(attrs, options); + this.changed = {}; + this.initialize.apply(this, arguments); + }; + + // Attach all inheritable methods to the Model prototype. + _.extend(Model.prototype, Events, { + + // A hash of attributes whose current and previous value differ. + changed: null, + + // The value returned during the last failed validation. + validationError: null, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute: 'id', + + // The prefix is used to create the client id which is used to identify models locally. + // You may want to override this if you're experiencing name clashes with model ids. + cidPrefix: 'c', + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Return a copy of the model's `attributes` object. + toJSON: function(options) { + return _.clone(this.attributes); + }, + + // Proxy `Backbone.sync` by default -- but override this if you need + // custom syncing semantics for *this* particular model. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Get the value of an attribute. + get: function(attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape: function(attr) { + return _.escape(this.get(attr)); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has: function(attr) { + return this.get(attr) != null; + }, + + // Special-cased proxy to underscore's `_.matches` method. + matches: function(attrs) { + return !!_.iteratee(attrs, this)(this.attributes); + }, + + // Set a hash of model attributes on the object, firing `"change"`. This is + // the core primitive operation of a model, updating the data and notifying + // anyone who needs to know about the change in state. The heart of the beast. + set: function(key, val, options) { + if (key == null) return this; + + // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options || (options = {}); + + // Run validation. + if (!this._validate(attrs, options)) return false; + + // Extract attributes and options. + var unset = options.unset; + var silent = options.silent; + var changes = []; + var changing = this._changing; + this._changing = true; + + if (!changing) { + this._previousAttributes = _.clone(this.attributes); + this.changed = {}; + } + + var current = this.attributes; + var changed = this.changed; + var prev = this._previousAttributes; + + // For each `set` attribute, update or delete the current value. + for (var attr in attrs) { + val = attrs[attr]; + if (!_.isEqual(current[attr], val)) changes.push(attr); + if (!_.isEqual(prev[attr], val)) { + changed[attr] = val; + } else { + delete changed[attr]; + } + unset ? delete current[attr] : current[attr] = val; + } + + // Update the `id`. + this.id = this.get(this.idAttribute); + + // Trigger all relevant attribute changes. + if (!silent) { + if (changes.length) this._pending = options; + for (var i = 0; i < changes.length; i++) { + this.trigger('change:' + changes[i], this, current[changes[i]], options); + } + } + + // You might be wondering why there's a `while` loop here. Changes can + // be recursively nested within `"change"` events. + if (changing) return this; + if (!silent) { + while (this._pending) { + options = this._pending; + this._pending = false; + this.trigger('change', this, options); + } + } + this._pending = false; + this._changing = false; + return this; + }, + + // Remove an attribute from the model, firing `"change"`. `unset` is a noop + // if the attribute doesn't exist. + unset: function(attr, options) { + return this.set(attr, void 0, _.extend({}, options, {unset: true})); + }, + + // Clear all attributes on the model, firing `"change"`. + clear: function(options) { + var attrs = {}; + for (var key in this.attributes) attrs[key] = void 0; + return this.set(attrs, _.extend({}, options, {unset: true})); + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged: function(attr) { + if (attr == null) return !_.isEmpty(this.changed); + return _.has(this.changed, attr); + }, + + // Return an object containing all the attributes that have changed, or + // false if there are no changed attributes. Useful for determining what + // parts of a view need to be updated and/or what attributes need to be + // persisted to the server. Unset attributes will be set to undefined. + // You can also pass an attributes object to diff against the model, + // determining if there *would be* a change. + changedAttributes: function(diff) { + if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; + var old = this._changing ? this._previousAttributes : this.attributes; + var changed = {}; + for (var attr in diff) { + var val = diff[attr]; + if (_.isEqual(old[attr], val)) continue; + changed[attr] = val; + } + return _.size(changed) ? changed : false; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous: function(attr) { + if (attr == null || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes: function() { + return _.clone(this._previousAttributes); + }, + + // Fetch the model from the server, merging the response with the model's + // local attributes. Any changed attributes will trigger a "change" event. + fetch: function(options) { + options = _.extend({parse: true}, options); + var model = this; + var success = options.success; + options.success = function(resp) { + var serverAttrs = options.parse ? model.parse(resp, options) : resp; + if (!model.set(serverAttrs, options)) return false; + if (success) success.call(options.context, model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save: function(key, val, options) { + // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; + if (key == null || typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options = _.extend({validate: true, parse: true}, options); + var wait = options.wait; + + // If we're not waiting and attributes exist, save acts as + // `set(attr).save(null, opts)` with validation. Otherwise, check if + // the model will be valid when the attributes, if any, are set. + if (attrs && !wait) { + if (!this.set(attrs, options)) return false; + } else { + if (!this._validate(attrs, options)) return false; + } + + // After a successful server-side save, the client is (optionally) + // updated with the server-side state. + var model = this; + var success = options.success; + var attributes = this.attributes; + options.success = function(resp) { + // Ensure attributes are restored during synchronous saves. + model.attributes = attributes; + var serverAttrs = options.parse ? model.parse(resp, options) : resp; + if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); + if (serverAttrs && !model.set(serverAttrs, options)) return false; + if (success) success.call(options.context, model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + + // Set temporary attributes if `{wait: true}` to properly find new ids. + if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); + + var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); + if (method === 'patch' && !options.attrs) options.attrs = attrs; + var xhr = this.sync(method, this, options); + + // Restore attributes. + this.attributes = attributes; + + return xhr; + }, + + // Destroy this model on the server if it was already persisted. + // Optimistically removes the model from its collection, if it has one. + // If `wait: true` is passed, waits for the server to respond before removal. + destroy: function(options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + var wait = options.wait; + + var destroy = function() { + model.stopListening(); + model.trigger('destroy', model, model.collection, options); + }; + + options.success = function(resp) { + if (wait) destroy(); + if (success) success.call(options.context, model, resp, options); + if (!model.isNew()) model.trigger('sync', model, resp, options); + }; + + var xhr = false; + if (this.isNew()) { + _.defer(options.success); + } else { + wrapError(this, options); + xhr = this.sync('delete', this, options); + } + if (!wait) destroy(); + return xhr; + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url: function() { + var base = + _.result(this, 'urlRoot') || + _.result(this.collection, 'url') || + urlError(); + if (this.isNew()) return base; + var id = this.get(this.idAttribute); + return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse: function(resp, options) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone: function() { + return new this.constructor(this.attributes); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew: function() { + return !this.has(this.idAttribute); + }, + + // Check if the model is currently in a valid state. + isValid: function(options) { + return this._validate({}, _.defaults({validate: true}, options)); + }, + + // Run validation against the next complete set of model attributes, + // returning `true` if all is well. Otherwise, fire an `"invalid"` event. + _validate: function(attrs, options) { + if (!options.validate || !this.validate) return true; + attrs = _.extend({}, this.attributes, attrs); + var error = this.validationError = this.validate(attrs, options) || null; + if (!error) return true; + this.trigger('invalid', this, error, _.extend(options, {validationError: error})); + return false; + } + + }); + + // Underscore methods that we want to implement on the Model, mapped to the + // number of arguments they take. + var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0, + omit: 0, chain: 1, isEmpty: 1 }; + + // Mix in each Underscore method as a proxy to `Model#attributes`. + addUnderscoreMethods(Model, modelMethods, 'attributes'); + + // Backbone.Collection + // ------------------- + + // If models tend to represent a single row of data, a Backbone Collection is + // more analogous to a table full of data ... or a small slice or page of that + // table, or a collection of rows that belong together for a particular reason + // -- all of the messages in this particular folder, all of the documents + // belonging to this particular author, and so on. Collections maintain + // indexes of their models, both in order, and for lookup by `id`. + + // Create a new **Collection**, perhaps to contain a specific type of `model`. + // If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + var Collection = Backbone.Collection = function(models, options) { + options || (options = {}); + if (options.model) this.model = options.model; + if (options.comparator !== void 0) this.comparator = options.comparator; + this._reset(); + this.initialize.apply(this, arguments); + if (models) this.reset(models, _.extend({silent: true}, options)); + }; + + // Default options for `Collection#set`. + var setOptions = {add: true, remove: true, merge: true}; + var addOptions = {add: true, remove: false}; + + // Splices `insert` into `array` at index `at`. + var splice = function(array, insert, at) { + at = Math.min(Math.max(at, 0), array.length); + var tail = Array(array.length - at); + var length = insert.length; + for (var i = 0; i < tail.length; i++) tail[i] = array[i + at]; + for (i = 0; i < length; i++) array[i + at] = insert[i]; + for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i]; + }; + + // Define the Collection's inheritable methods. + _.extend(Collection.prototype, Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model: Model, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON: function(options) { + return this.map(function(model) { return model.toJSON(options); }); + }, + + // Proxy `Backbone.sync` by default. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Add a model, or list of models to the set. `models` may be Backbone + // Models or raw JavaScript objects to be converted to Models, or any + // combination of the two. + add: function(models, options) { + return this.set(models, _.extend({merge: false}, options, addOptions)); + }, + + // Remove a model, or a list of models from the set. + remove: function(models, options) { + options = _.extend({}, options); + var singular = !_.isArray(models); + models = singular ? [models] : _.clone(models); + var removed = this._removeModels(models, options); + if (!options.silent && removed) this.trigger('update', this, options); + return singular ? removed[0] : removed; + }, + + // Update a collection by `set`-ing a new list of models, adding new ones, + // removing models that are no longer present, and merging models that + // already exist in the collection, as necessary. Similar to **Model#set**, + // the core operation for updating the data contained by the collection. + set: function(models, options) { + if (models == null) return; + + options = _.defaults({}, options, setOptions); + if (options.parse && !this._isModel(models)) models = this.parse(models, options); + + var singular = !_.isArray(models); + models = singular ? [models] : models.slice(); + + var at = options.at; + if (at != null) at = +at; + if (at < 0) at += this.length + 1; + + var set = []; + var toAdd = []; + var toRemove = []; + var modelMap = {}; + + var add = options.add; + var merge = options.merge; + var remove = options.remove; + + var sort = false; + var sortable = this.comparator && (at == null) && options.sort !== false; + var sortAttr = _.isString(this.comparator) ? this.comparator : null; + + // Turn bare objects into model references, and prevent invalid models + // from being added. + var model; + for (var i = 0; i < models.length; i++) { + model = models[i]; + + // If a duplicate is found, prevent it from being added and + // optionally merge it into the existing model. + var existing = this.get(model); + if (existing) { + if (merge && model !== existing) { + var attrs = this._isModel(model) ? model.attributes : model; + if (options.parse) attrs = existing.parse(attrs, options); + existing.set(attrs, options); + if (sortable && !sort) sort = existing.hasChanged(sortAttr); + } + if (!modelMap[existing.cid]) { + modelMap[existing.cid] = true; + set.push(existing); + } + models[i] = existing; + + // If this is a new, valid model, push it to the `toAdd` list. + } else if (add) { + model = models[i] = this._prepareModel(model, options); + if (model) { + toAdd.push(model); + this._addReference(model, options); + modelMap[model.cid] = true; + set.push(model); + } + } + } + + // Remove stale models. + if (remove) { + for (i = 0; i < this.length; i++) { + model = this.models[i]; + if (!modelMap[model.cid]) toRemove.push(model); + } + if (toRemove.length) this._removeModels(toRemove, options); + } + + // See if sorting is needed, update `length` and splice in new models. + var orderChanged = false; + var replace = !sortable && add && remove; + if (set.length && replace) { + orderChanged = this.length != set.length || _.some(this.models, function(model, index) { + return model !== set[index]; + }); + this.models.length = 0; + splice(this.models, set, 0); + this.length = this.models.length; + } else if (toAdd.length) { + if (sortable) sort = true; + splice(this.models, toAdd, at == null ? this.length : at); + this.length = this.models.length; + } + + // Silently sort the collection if appropriate. + if (sort) this.sort({silent: true}); + + // Unless silenced, it's time to fire all appropriate add/sort events. + if (!options.silent) { + for (i = 0; i < toAdd.length; i++) { + if (at != null) options.index = at + i; + model = toAdd[i]; + model.trigger('add', model, this, options); + } + if (sort || orderChanged) this.trigger('sort', this, options); + if (toAdd.length || toRemove.length) this.trigger('update', this, options); + } + + // Return the added (or merged) model (or models). + return singular ? models[0] : models; + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any granular `add` or `remove` events. Fires `reset` when finished. + // Useful for bulk operations and optimizations. + reset: function(models, options) { + options = options ? _.clone(options) : {}; + for (var i = 0; i < this.models.length; i++) { + this._removeReference(this.models[i], options); + } + options.previousModels = this.models; + this._reset(); + models = this.add(models, _.extend({silent: true}, options)); + if (!options.silent) this.trigger('reset', this, options); + return models; + }, + + // Add a model to the end of the collection. + push: function(model, options) { + return this.add(model, _.extend({at: this.length}, options)); + }, + + // Remove a model from the end of the collection. + pop: function(options) { + var model = this.at(this.length - 1); + return this.remove(model, options); + }, + + // Add a model to the beginning of the collection. + unshift: function(model, options) { + return this.add(model, _.extend({at: 0}, options)); + }, + + // Remove a model from the beginning of the collection. + shift: function(options) { + var model = this.at(0); + return this.remove(model, options); + }, + + // Slice out a sub-array of models from the collection. + slice: function() { + return slice.apply(this.models, arguments); + }, + + // Get a model from the set by id. + get: function(obj) { + if (obj == null) return void 0; + var id = this.modelId(this._isModel(obj) ? obj.attributes : obj); + return this._byId[obj] || this._byId[id] || this._byId[obj.cid]; + }, + + // Get the model at the given index. + at: function(index) { + if (index < 0) index += this.length; + return this.models[index]; + }, + + // Return models with matching attributes. Useful for simple cases of + // `filter`. + where: function(attrs, first) { + return this[first ? 'find' : 'filter'](attrs); + }, + + // Return the first model with matching attributes. Useful for simple cases + // of `find`. + findWhere: function(attrs) { + return this.where(attrs, true); + }, + + // Force the collection to re-sort itself. You don't need to call this under + // normal circumstances, as the set will maintain sort order as each item + // is added. + sort: function(options) { + var comparator = this.comparator; + if (!comparator) throw new Error('Cannot sort a set without a comparator'); + options || (options = {}); + + var length = comparator.length; + if (_.isFunction(comparator)) comparator = _.bind(comparator, this); + + // Run sort based on type of `comparator`. + if (length === 1 || _.isString(comparator)) { + this.models = this.sortBy(comparator); + } else { + this.models.sort(comparator); + } + if (!options.silent) this.trigger('sort', this, options); + return this; + }, + + // Pluck an attribute from each model in the collection. + pluck: function(attr) { + return _.invoke(this.models, 'get', attr); + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `reset: true` is passed, the response + // data will be passed through the `reset` method instead of `set`. + fetch: function(options) { + options = _.extend({parse: true}, options); + var success = options.success; + var collection = this; + options.success = function(resp) { + var method = options.reset ? 'reset' : 'set'; + collection[method](resp, options); + if (success) success.call(options.context, collection, resp, options); + collection.trigger('sync', collection, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Create a new instance of a model in this collection. Add the model to the + // collection immediately, unless `wait: true` is passed, in which case we + // wait for the server to agree. + create: function(model, options) { + options = options ? _.clone(options) : {}; + var wait = options.wait; + model = this._prepareModel(model, options); + if (!model) return false; + if (!wait) this.add(model, options); + var collection = this; + var success = options.success; + options.success = function(model, resp, callbackOpts) { + if (wait) collection.add(model, callbackOpts); + if (success) success.call(callbackOpts.context, model, resp, callbackOpts); + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse: function(resp, options) { + return resp; + }, + + // Create a new collection with an identical list of models as this one. + clone: function() { + return new this.constructor(this.models, { + model: this.model, + comparator: this.comparator + }); + }, + + // Define how to uniquely identify models in the collection. + modelId: function (attrs) { + return attrs[this.model.prototype.idAttribute || 'id']; + }, + + // Private method to reset all internal state. Called when the collection + // is first initialized or reset. + _reset: function() { + this.length = 0; + this.models = []; + this._byId = {}; + }, + + // Prepare a hash of attributes (or other model) to be added to this + // collection. + _prepareModel: function(attrs, options) { + if (this._isModel(attrs)) { + if (!attrs.collection) attrs.collection = this; + return attrs; + } + options = options ? _.clone(options) : {}; + options.collection = this; + var model = new this.model(attrs, options); + if (!model.validationError) return model; + this.trigger('invalid', this, model.validationError, options); + return false; + }, + + // Internal method called by both remove and set. + _removeModels: function(models, options) { + var removed = []; + for (var i = 0; i < models.length; i++) { + var model = this.get(models[i]); + if (!model) continue; + + var index = this.indexOf(model); + this.models.splice(index, 1); + this.length--; + + if (!options.silent) { + options.index = index; + model.trigger('remove', model, this, options); + } + + removed.push(model); + this._removeReference(model, options); + } + return removed.length ? removed : false; + }, + + // Method for checking whether an object should be considered a model for + // the purposes of adding to the collection. + _isModel: function (model) { + return model instanceof Model; + }, + + // Internal method to create a model's ties to a collection. + _addReference: function(model, options) { + this._byId[model.cid] = model; + var id = this.modelId(model.attributes); + if (id != null) this._byId[id] = model; + model.on('all', this._onModelEvent, this); + }, + + // Internal method to sever a model's ties to a collection. + _removeReference: function(model, options) { + delete this._byId[model.cid]; + var id = this.modelId(model.attributes); + if (id != null) delete this._byId[id]; + if (this === model.collection) delete model.collection; + model.off('all', this._onModelEvent, this); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent: function(event, model, collection, options) { + if ((event === 'add' || event === 'remove') && collection !== this) return; + if (event === 'destroy') this.remove(model, options); + if (event === 'change') { + var prevId = this.modelId(model.previousAttributes()); + var id = this.modelId(model.attributes); + if (prevId !== id) { + if (prevId != null) delete this._byId[prevId]; + if (id != null) this._byId[id] = model; + } + } + this.trigger.apply(this, arguments); + } + + }); + + // Underscore methods that we want to implement on the Collection. + // 90% of the core usefulness of Backbone Collections is actually implemented + // right here: + var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, + foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, + select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, + contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, + head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, + without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, + isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3, + sortBy: 3, indexBy: 3}; + + // Mix in each Underscore method as a proxy to `Collection#models`. + addUnderscoreMethods(Collection, collectionMethods, 'models'); + + // Backbone.View + // ------------- + + // Backbone Views are almost more convention than they are actual code. A View + // is simply a JavaScript object that represents a logical chunk of UI in the + // DOM. This might be a single item, an entire list, a sidebar or panel, or + // even the surrounding frame which wraps your whole app. Defining a chunk of + // UI as a **View** allows you to define your DOM events declaratively, without + // having to worry about render order ... and makes it easy for the view to + // react to specific changes in the state of your models. + + // Creating a Backbone.View creates its initial element outside of the DOM, + // if an existing element is not provided... + var View = Backbone.View = function(options) { + this.cid = _.uniqueId('view'); + _.extend(this, _.pick(options, viewOptions)); + this._ensureElement(); + this.initialize.apply(this, arguments); + }; + + // Cached regex to split keys for `delegate`. + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + // List of view options to be set as properties. + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + // Set up all inheritable **Backbone.View** properties and methods. + _.extend(View.prototype, Events, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + // jQuery delegate for element lookup, scoped to DOM elements within the + // current view. This should be preferred to global lookups where possible. + $: function(selector) { + return this.$el.find(selector); + }, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // **render** is the core function that your view should override, in order + // to populate its element (`this.el`), with the appropriate HTML. The + // convention is for **render** to always return `this`. + render: function() { + return this; + }, + + // Remove this view by taking the element out of the DOM, and removing any + // applicable Backbone.Events listeners. + remove: function() { + this._removeElement(); + this.stopListening(); + return this; + }, + + // Remove this view's element from the document and all event listeners + // attached to it. Exposed for subclasses using an alternative DOM + // manipulation API. + _removeElement: function() { + this.$el.remove(); + }, + + // Change the view's element (`this.el` property) and re-delegate the + // view's events on the new element. + setElement: function(element) { + this.undelegateEvents(); + this._setElement(element); + this.delegateEvents(); + return this; + }, + + // Creates the `this.el` and `this.$el` references for this view using the + // given `el`. `el` can be a CSS selector or an HTML string, a jQuery + // context or an element. Subclasses can override this to utilize an + // alternative DOM manipulation API and are only required to set the + // `this.el` property. + _setElement: function(el) { + this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); + this.el = this.$el[0]; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + delegateEvents: function(events) { + events || (events = _.result(this, 'events')); + if (!events) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[method]; + if (!method) continue; + var match = key.match(delegateEventSplitter); + this.delegate(match[1], match[2], _.bind(method, this)); + } + return this; + }, + + // Add a single event listener to the view's element (or a child element + // using `selector`). This only works for delegate-able events: not `focus`, + // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. + delegate: function(eventName, selector, listener) { + this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; + }, + + // Clears all callbacks previously bound to the view by `delegateEvents`. + // You usually don't need to use this, but may wish to if you have multiple + // Backbone views attached to the same DOM element. + undelegateEvents: function() { + if (this.$el) this.$el.off('.delegateEvents' + this.cid); + return this; + }, + + // A finer-grained `undelegateEvents` for removing a single delegated event. + // `selector` and `listener` are both optional. + undelegate: function(eventName, selector, listener) { + this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; + }, + + // Produces a DOM element to be assigned to your view. Exposed for + // subclasses using an alternative DOM manipulation API. + _createElement: function(tagName) { + return document.createElement(tagName); + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + if (!this.el) { + var attrs = _.extend({}, _.result(this, 'attributes')); + if (this.id) attrs.id = _.result(this, 'id'); + if (this.className) attrs['class'] = _.result(this, 'className'); + this.setElement(this._createElement(_.result(this, 'tagName'))); + this._setAttributes(attrs); + } else { + this.setElement(_.result(this, 'el')); + } + }, + + // Set attributes from a hash on this view's element. Exposed for + // subclasses using an alternative DOM manipulation API. + _setAttributes: function(attributes) { + this.$el.attr(attributes); + } + + }); + + // Backbone.sync + // ------------- + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + // Pass along `textStatus` and `errorThrown` from jQuery. + var error = options.error; + options.error = function(xhr, textStatus, errorThrown) { + options.textStatus = textStatus; + options.errorThrown = errorThrown; + if (error) error.call(options.context, xhr, textStatus, errorThrown); + }; + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + 'create': 'POST', + 'update': 'PUT', + 'patch': 'PATCH', + 'delete': 'DELETE', + 'read': 'GET' + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + // Override this if you'd like to use a different library. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Backbone.Router + // --------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function(options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route: function(route, name, callback) { + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (_.isFunction(name)) { + callback = name; + name = ''; + } + if (!callback) callback = this[name]; + var router = this; + Backbone.history.route(route, function(fragment) { + var args = router._extractParameters(route, fragment); + if (router.execute(callback, args, name) !== false) { + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); + } + }); + return this; + }, + + // Execute a route handler with the provided parameters. This is an + // excellent place to do pre-route setup or post-route cleanup. + execute: function(callback, args, name) { + if (callback) callback.apply(this, args); + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate: function(fragment, options) { + Backbone.history.navigate(fragment, options); + return this; + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes: function() { + if (!this.routes) return; + this.routes = _.result(this, 'routes'); + var route, routes = _.keys(this.routes); + while ((route = routes.pop()) != null) { + this.route(route, this.routes[route]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional) { + return optional ? match : '([^/?]+)'; + }) + .replace(splatParam, '([^?]*?)'); + return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + return _.map(params, function(param, i) { + // Don't decode the search params. + if (i === params.length - 1) return param || null; + return param ? decodeURIComponent(param) : null; + }); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on either + // [pushState](http://diveintohtml5.info/history.html) and real URLs, or + // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) + // and URL fragments. If the browser supports neither (old IE, natch), + // falls back to polling. + var History = Backbone.History = function() { + this.handlers = []; + this.checkUrl = _.bind(this.checkUrl, this); + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } + }; + + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for stripping urls of hash. + var pathStripper = /#.*$/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Are we at the app root? + atRoot: function() { + var path = this.location.pathname.replace(/[^\/]$/, '$&/'); + return path === this.root && !this.getSearch(); + }, + + // Does the pathname match the root? + matchRoot: function() { + var path = this.decodeFragment(this.location.pathname); + var root = path.slice(0, this.root.length - 1) + '/'; + return root === this.root; + }, + + // Unicode characters in `location.pathname` are percent encoded so they're + // decoded for comparison. `%25` should not be decoded since it may be part + // of an encoded parameter. + decodeFragment: function(fragment) { + return decodeURI(fragment.replace(/%25/g, '%2525')); + }, + + // In IE6, the hash fragment and search params are incorrect if the + // fragment contains `?`. + getSearch: function() { + var match = this.location.href.replace(/#.*/, '').match(/\?.+/); + return match ? match[0] : ''; + }, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(window) { + var match = (window || this).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the pathname and search params, without the root. + getPath: function() { + var path = this.decodeFragment( + this.location.pathname + this.getSearch() + ).slice(this.root.length - 1); + return path.charAt(0) === '/' ? path.slice(1) : path; + }, + + // Get the cross-browser normalized URL fragment from the path or hash. + getFragment: function(fragment) { + if (fragment == null) { + if (this._usePushState || !this._wantsHashChange) { + fragment = this.getPath(); + } else { + fragment = this.getHash(); + } + } + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start: function(options) { + if (History.started) throw new Error('Backbone.history has already been started'); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({root: '/'}, this.options, options); + this.root = this.options.root; + this._wantsHashChange = this.options.hashChange !== false; + this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7); + this._useHashChange = this._wantsHashChange && this._hasHashChange; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.history && this.history.pushState); + this._usePushState = this._wantsPushState && this._hasPushState; + this.fragment = this.getFragment(); + + // Normalize root to always include a leading and trailing slash. + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); + + // Transition from hashChange to pushState or vice versa if both are + // requested. + if (this._wantsHashChange && this._wantsPushState) { + + // If we've started off with a route from a `pushState`-enabled + // browser, but we're currently in a browser that doesn't support it... + if (!this._hasPushState && !this.atRoot()) { + var root = this.root.slice(0, -1) || '/'; + this.location.replace(root + '#' + this.getPath()); + // Return immediately as browser will do redirect to new url + return true; + + // Or if we've started out with a hash-based route, but we're currently + // in a browser where it could be `pushState`-based instead... + } else if (this._hasPushState && this.atRoot()) { + this.navigate(this.getHash(), {replace: true}); + } + + } + + // Proxy an iframe to handle location events if the browser doesn't + // support the `hashchange` event, HTML5 history, or the user wants + // `hashChange` but not `pushState`. + if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { + this.iframe = document.createElement('iframe'); + this.iframe.src = 'javascript:0'; + this.iframe.style.display = 'none'; + this.iframe.tabIndex = -1; + var body = document.body; + // Using `appendChild` will throw on IE < 9 if the document is not ready. + var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; + iWindow.document.open(); + iWindow.document.close(); + iWindow.location.hash = '#' + this.fragment; + } + + // Add a cross-platform `addEventListener` shim for older browsers. + var addEventListener = window.addEventListener || function (eventName, listener) { + return attachEvent('on' + eventName, listener); + }; + + // Depending on whether we're using pushState or hashes, and whether + // 'onhashchange' is supported, determine how we check the URL state. + if (this._usePushState) { + addEventListener('popstate', this.checkUrl, false); + } else if (this._useHashChange && !this.iframe) { + addEventListener('hashchange', this.checkUrl, false); + } else if (this._wantsHashChange) { + this._checkUrlInterval = setInterval(this.checkUrl, this.interval); + } + + if (!this.options.silent) return this.loadUrl(); + }, + + // Disable Backbone.history, perhaps temporarily. Not useful in a real app, + // but possibly useful for unit testing Routers. + stop: function() { + // Add a cross-platform `removeEventListener` shim for older browsers. + var removeEventListener = window.removeEventListener || function (eventName, listener) { + return detachEvent('on' + eventName, listener); + }; + + // Remove window listeners. + if (this._usePushState) { + removeEventListener('popstate', this.checkUrl, false); + } else if (this._useHashChange && !this.iframe) { + removeEventListener('hashchange', this.checkUrl, false); + } + + // Clean up the iframe if necessary. + if (this.iframe) { + document.body.removeChild(this.iframe); + this.iframe = null; + } + + // Some environments will throw when clearing an undefined interval. + if (this._checkUrlInterval) clearInterval(this._checkUrlInterval); + History.started = false; + }, + + // Add a route to be tested when the fragment changes. Routes added later + // may override previous routes. + route: function(route, callback) { + this.handlers.unshift({route: route, callback: callback}); + }, + + // Checks the current URL to see if it has changed, and if it has, + // calls `loadUrl`, normalizing across the hidden iframe. + checkUrl: function(e) { + var current = this.getFragment(); + + // If the user pressed the back button, the iframe's hash will have + // changed and we should use that for comparison. + if (current === this.fragment && this.iframe) { + current = this.getHash(this.iframe.contentWindow); + } + + if (current === this.fragment) return false; + if (this.iframe) this.navigate(current); + this.loadUrl(); + }, + + // Attempt to load the current URL fragment. If a route succeeds with a + // match, returns `true`. If no defined routes matches the fragment, + // returns `false`. + loadUrl: function(fragment) { + // If the root doesn't match, no routes can match either. + if (!this.matchRoot()) return false; + fragment = this.fragment = this.getFragment(fragment); + return _.some(this.handlers, function(handler) { + if (handler.route.test(fragment)) { + handler.callback(fragment); + return true; + } + }); + }, + + // Save a fragment into the hash history, or replace the URL state if the + // 'replace' option is passed. You are responsible for properly URL-encoding + // the fragment in advance. + // + // The options object can contain `trigger: true` if you wish to have the + // route callback be fired (not usually desirable), or `replace: true`, if + // you wish to modify the current URL without adding an entry to the history. + navigate: function(fragment, options) { + if (!History.started) return false; + if (!options || options === true) options = {trigger: !!options}; + + // Normalize the fragment. + fragment = this.getFragment(fragment || ''); + + // Don't include a trailing slash on the root. + var root = this.root; + if (fragment === '' || fragment.charAt(0) === '?') { + root = root.slice(0, -1) || '/'; + } + var url = root + fragment; + + // Strip the hash and decode for matching. + fragment = this.decodeFragment(fragment.replace(pathStripper, '')); + + if (this.fragment === fragment) return; + this.fragment = fragment; + + // If pushState is available, we use it to set the fragment as a real URL. + if (this._usePushState) { + this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); + + // If hash changes haven't been explicitly disabled, update the hash + // fragment to store history. + } else if (this._wantsHashChange) { + this._updateHash(this.location, fragment, options.replace); + if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) { + var iWindow = this.iframe.contentWindow; + + // Opening and closing the iframe tricks IE7 and earlier to push a + // history entry on hash-tag change. When replace is true, we don't + // want this. + if (!options.replace) { + iWindow.document.open(); + iWindow.document.close(); + } + + this._updateHash(iWindow.location, fragment, options.replace); + } + + // If you've told us that you explicitly don't want fallback hashchange- + // based history, then `navigate` becomes a page refresh. + } else { + return this.location.assign(url); + } + if (options.trigger) return this.loadUrl(fragment); + }, + + // Update the hash location, either replacing the current entry, or adding + // a new one to the browser history. + _updateHash: function(location, fragment, replace) { + if (replace) { + var href = location.href.replace(/(javascript:|#).*$/, ''); + location.replace(href + '#' + fragment); + } else { + // Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; + } + } + + }); + + // Create the default Backbone.history. + Backbone.history = new History; + + // Helpers + // ------- + + // Helper function to correctly set up the prototype chain for subclasses. + // Similar to `goog.inherits`, but uses a hash of prototype properties and + // class properties to be extended. + var extend = function(protoProps, staticProps) { + var parent = this; + var child; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent` constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); + + // Set a convenience property in case the parent's prototype is needed + // later. + child.__super__ = parent.prototype; + + return child; + }; + + // Set up inheritance for the model, collection, router, view and history. + Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; + + // Throw an error when a URL is needed, and none is supplied. + var urlError = function() { + throw new Error('A "url" property or function must be specified'); + }; + + // Wrap an optional error callback with a fallback error event. + var wrapError = function(model, options) { + var error = options.error; + options.error = function(resp) { + if (error) error.call(options.context, model, resp, options); + model.trigger('error', model, resp, options); + }; + }; + + return Backbone; + +})); diff --git a/src/frontend/static/lib/bootstrap b/src/frontend/static/lib/bootstrap new file mode 120000 index 0000000..257666d --- /dev/null +++ b/src/frontend/static/lib/bootstrap @@ -0,0 +1 @@ +bootstrap-3.3.5-dist/ \ No newline at end of file diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-outline.svg b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-outline.svg new file mode 100644 index 0000000..9f9794c --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-outline.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-punchout.svg b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-punchout.svg new file mode 100644 index 0000000..7368058 --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-punchout.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-solid.svg b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-solid.svg new file mode 100644 index 0000000..6c2211d --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/brand/bootstrap-solid.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/docs.min.css b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/docs.min.css new file mode 100644 index 0000000..d2a06ca --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/docs.min.css @@ -0,0 +1,6 @@ +.hll{background-color:#ffc}.c{color:#999}.err{color:#A00;background-color:#FAA}.k{color:#069}.o{color:#555}.cm{color:#999}.cp{color:#099}.c1{color:#999}.cs{color:#999}.gd{background-color:#FCC;border:1px solid #C00}.ge{font-style:italic}.gr{color:red}.gh{color:#030}.gi{background-color:#CFC;border:1px solid #0C0}.go{color:#AAA}.gp{color:#009}.gu{color:#030}.gt{color:#9C6}.kc{color:#069}.kd{color:#069}.kn{color:#069}.kp{color:#069}.kr{color:#069}.kt{color:#078}.m{color:#F60}.s{color:#d44950}.na{color:#4f9fcf}.nb{color:#366}.nc{color:#0A8}.no{color:#360}.nd{color:#99F}.ni{color:#999}.ne{color:#C00}.nf{color:#C0F}.nl{color:#99F}.nn{color:#0CF}.nt{color:#2f6f9f}.nv{color:#033}.ow{color:#000}.w{color:#bbb}.mf{color:#F60}.mh{color:#F60}.mi{color:#F60}.mo{color:#F60}.sb{color:#C30}.sc{color:#C30}.sd{color:#C30;font-style:italic}.s2{color:#C30}.se{color:#C30}.sh{color:#C30}.si{color:#A00}.sx{color:#C30}.sr{color:#3AA}.s1{color:#C30}.ss{color:#FC3}.bp{color:#366}.vc{color:#033}.vg{color:#033}.vi{color:#033}.il{color:#F60}.css .nt+.nt,.css .o,.css .o+.nt{color:#999}/*! + * Bootstrap Docs (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under the Creative Commons Attribution 3.0 Unported License. For + * details, see https://creativecommons.org/licenses/by/3.0/. + */body{position:relative}.table code{font-size:13px;font-weight:400}h2 code,h3 code,h4 code{background-color:inherit}.btn-outline{color:#563d7c;background-color:transparent;border-color:#563d7c}.btn-outline:active,.btn-outline:focus,.btn-outline:hover{color:#fff;background-color:#563d7c;border-color:#563d7c}.btn-outline-inverse{color:#fff;background-color:transparent;border-color:#cdbfe3}.btn-outline-inverse:active,.btn-outline-inverse:focus,.btn-outline-inverse:hover{color:#563d7c;text-shadow:none;background-color:#fff;border-color:#fff}.bs-docs-booticon{display:block;font-weight:500;color:#fff;text-align:center;cursor:default;background-color:#563d7c;border-radius:15%}.bs-docs-booticon-sm{width:30px;height:30px;font-size:20px;line-height:28px}.bs-docs-booticon-lg{width:144px;height:144px;font-size:108px;line-height:140px}.bs-docs-booticon-inverse{color:#563d7c;background-color:#fff}.bs-docs-booticon-outline{background-color:transparent;border:1px solid #cdbfe3}#skippy{display:block;padding:1em;color:#fff;background-color:#6f5499;outline:0}#skippy .skiplink-text{padding:.5em;outline:1px dotted}#content:focus{outline:0}.bs-docs-nav{margin-bottom:0;background-color:#fff;border-bottom:0}.bs-home-nav .bs-nav-b{display:none}.bs-docs-nav .navbar-brand,.bs-docs-nav .navbar-nav>li>a{font-weight:500;color:#563d7c}.bs-docs-nav .navbar-nav>.active>a,.bs-docs-nav .navbar-nav>.active>a:hover,.bs-docs-nav .navbar-nav>li>a:hover{color:#463265;background-color:#f9f9f9}.bs-docs-nav .navbar-toggle .icon-bar{background-color:#563d7c}.bs-docs-nav .navbar-header .navbar-toggle{border-color:#fff}.bs-docs-nav .navbar-header .navbar-toggle:focus,.bs-docs-nav .navbar-header .navbar-toggle:hover{background-color:#f9f9f9;border-color:#f9f9f9}.bs-docs-footer{padding-top:40px;padding-bottom:40px;margin-top:100px;color:#767676;text-align:center;border-top:1px solid #e5e5e5}.bs-docs-footer-links{padding-left:0;margin-top:20px}.bs-docs-footer-links li{display:inline;padding:0 2px}.bs-docs-footer-links li:first-child{padding-left:0}@media (min-width:768px){.bs-docs-footer p{margin-bottom:0}}.bs-docs-social{margin-bottom:20px;text-align:center}.bs-docs-social-buttons{display:inline-block;padding-left:0;margin-bottom:0;list-style:none}.bs-docs-social-buttons li{display:inline-block;padding:5px 8px;line-height:1}.bs-docs-social-buttons .twitter-follow-button{width:225px!important}.bs-docs-social-buttons .twitter-share-button{width:98px!important}.github-btn{overflow:hidden;border:0}.bs-docs-header,.bs-docs-masthead{position:relative;padding:30px 0;color:#cdbfe3;text-align:center;text-shadow:0 1px 0 rgba(0,0,0,.1);background-color:#6f5499;background-image:-webkit-gradient(linear,left top,left bottom,from(#563d7c),to(#6f5499));background-image:-webkit-linear-gradient(top,#563d7c 0,#6f5499 100%);background-image:-o-linear-gradient(top,#563d7c 0,#6f5499 100%);background-image:linear-gradient(to bottom,#563d7c 0,#6f5499 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#563d7c', endColorstr='#6F5499', GradientType=0);background-repeat:repeat-x}.bs-docs-masthead .bs-docs-booticon{margin:0 auto 30px}.bs-docs-masthead h1{font-weight:300;line-height:1;color:#fff}.bs-docs-masthead .lead{margin:0 auto 30px;font-size:20px;color:#fff}.bs-docs-masthead .version{margin-top:-15px;margin-bottom:30px;color:#9783b9}.bs-docs-masthead .btn{width:100%;padding:15px 30px;font-size:20px}@media (min-width:480px){.bs-docs-masthead .btn{width:auto}}@media (min-width:768px){.bs-docs-masthead{padding:80px 0}.bs-docs-masthead h1{font-size:60px}.bs-docs-masthead .lead{font-size:24px}}@media (min-width:992px){.bs-docs-masthead .lead{width:80%;font-size:30px}}.bs-docs-header{margin-bottom:40px;font-size:20px}.bs-docs-header h1{margin-top:0;color:#fff}.bs-docs-header p{margin-bottom:0;font-weight:300;line-height:1.4}.bs-docs-header .container{position:relative}@media (min-width:768px){.bs-docs-header{padding-top:60px;padding-bottom:60px;font-size:24px;text-align:left}.bs-docs-header h1{font-size:60px;line-height:1}}@media (min-width:992px){.bs-docs-header h1,.bs-docs-header p{margin-right:380px}}.carbonad{width:auto!important;height:auto!important;padding:20px!important;margin:30px -15px -31px!important;overflow:hidden;font-size:13px!important;line-height:16px!important;text-align:left;background:0 0!important;border:solid #866ab3!important;border-width:1px 0!important}.carbonad-img{margin:0!important}.carbonad-tag,.carbonad-text{display:block!important;float:none!important;width:auto!important;height:auto!important;margin-left:145px!important;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif!important}.carbonad-text{padding-top:0!important}.carbonad-tag{color:inherit!important;text-align:left!important}.carbonad-tag a,.carbonad-text a{color:#fff!important}.carbonad #azcarbon>img{display:none}@media (min-width:480px){.carbonad{width:330px!important;margin:20px auto!important;border-width:1px!important;border-radius:4px}.bs-docs-masthead .carbonad{margin:50px auto 0!important}}@media (min-width:768px){.carbonad{margin-right:0!important;margin-left:0!important}}@media (min-width:992px){.carbonad{position:absolute;top:0;right:15px;width:330px!important;padding:15px!important;margin:0!important}.bs-docs-masthead .carbonad{position:static}}.bs-docs-featurette{padding-top:40px;padding-bottom:40px;font-size:16px;line-height:1.5;color:#555;text-align:center;background-color:#fff;border-bottom:1px solid #e5e5e5}.bs-docs-featurette+.bs-docs-footer{margin-top:0;border-top:0}.bs-docs-featurette-title{margin-bottom:5px;font-size:30px;font-weight:400;color:#333}.half-rule{width:100px;margin:40px auto}.bs-docs-featurette h3{margin-bottom:5px;font-weight:400;color:#333}.bs-docs-featurette-img{display:block;margin-bottom:20px;color:#333}.bs-docs-featurette-img:hover{color:#337ab7;text-decoration:none}.bs-docs-featurette-img img{display:block;margin-bottom:15px}@media (min-width:480px){.bs-docs-featurette .img-responsive{margin-top:30px}}@media (min-width:768px){.bs-docs-featurette{padding-top:100px;padding-bottom:100px}.bs-docs-featurette-title{font-size:40px}.bs-docs-featurette .lead{max-width:80%;margin-right:auto;margin-left:auto}.bs-docs-featurette .img-responsive{margin-top:0}}.bs-docs-featured-sites{margin-right:-1px;margin-left:-1px}.bs-docs-featured-sites .col-xs-6{padding:1px}.bs-docs-featured-sites .img-responsive{margin-top:0}@media (min-width:768px){.bs-docs-featured-sites .col-sm-3:first-child img{border-top-left-radius:4px;border-bottom-left-radius:4px}.bs-docs-featured-sites .col-sm-3:last-child img{border-top-right-radius:4px;border-bottom-right-radius:4px}}.bs-examples .thumbnail{margin-bottom:10px}.bs-examples h4{margin-bottom:5px}.bs-examples p{margin-bottom:20px}@media (max-width:480px){.bs-examples{margin-right:-10px;margin-left:-10px}.bs-examples>[class^=col-]{padding-right:10px;padding-left:10px}}.bs-docs-sidebar.affix{position:static}@media (min-width:768px){.bs-docs-sidebar{padding-left:20px}}.bs-docs-sidenav{margin-top:20px;margin-bottom:20px}.bs-docs-sidebar .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}.bs-docs-sidebar .nav>li>a:focus,.bs-docs-sidebar .nav>li>a:hover{padding-left:19px;color:#563d7c;text-decoration:none;background-color:transparent;border-left:1px solid #563d7c}.bs-docs-sidebar .nav>.active:focus>a,.bs-docs-sidebar .nav>.active:hover>a,.bs-docs-sidebar .nav>.active>a{padding-left:18px;font-weight:700;color:#563d7c;background-color:transparent;border-left:2px solid #563d7c}.bs-docs-sidebar .nav .nav{display:none;padding-bottom:10px}.bs-docs-sidebar .nav .nav>li>a{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}.bs-docs-sidebar .nav .nav>li>a:focus,.bs-docs-sidebar .nav .nav>li>a:hover{padding-left:29px}.bs-docs-sidebar .nav .nav>.active:focus>a,.bs-docs-sidebar .nav .nav>.active:hover>a,.bs-docs-sidebar .nav .nav>.active>a{padding-left:28px;font-weight:500}.back-to-top,.bs-docs-theme-toggle{display:none;padding:4px 10px;margin-top:10px;margin-left:10px;font-size:12px;font-weight:500;color:#999}.back-to-top:hover,.bs-docs-theme-toggle:hover{color:#563d7c;text-decoration:none}.bs-docs-theme-toggle{margin-top:0}@media (min-width:768px){.back-to-top,.bs-docs-theme-toggle{display:block}}@media (min-width:992px){.bs-docs-sidebar .nav>.active>ul{display:block}.bs-docs-sidebar.affix,.bs-docs-sidebar.affix-bottom{width:213px}.bs-docs-sidebar.affix{position:fixed;top:20px}.bs-docs-sidebar.affix-bottom{position:absolute}.bs-docs-sidebar.affix .bs-docs-sidenav,.bs-docs-sidebar.affix-bottom .bs-docs-sidenav{margin-top:0;margin-bottom:0}}@media (min-width:1200px){.bs-docs-sidebar.affix,.bs-docs-sidebar.affix-bottom{width:263px}}.bs-docs-section{margin-bottom:60px}.bs-docs-section:last-child{margin-bottom:0}h1[id]{padding-top:20px;margin-top:0}.bs-callout{padding:20px;margin:20px 0;border:1px solid #eee;border-left-width:5px;border-radius:3px}.bs-callout h4{margin-top:0;margin-bottom:5px}.bs-callout p:last-child{margin-bottom:0}.bs-callout code{border-radius:3px}.bs-callout+.bs-callout{margin-top:-5px}.bs-callout-danger{border-left-color:#ce4844}.bs-callout-danger h4{color:#ce4844}.bs-callout-warning{border-left-color:#aa6708}.bs-callout-warning h4{color:#aa6708}.bs-callout-info{border-left-color:#1b809e}.bs-callout-info h4{color:#1b809e}.color-swatches{margin:0 -5px;overflow:hidden}.color-swatch{float:left;width:60px;height:60px;margin:0 5px;border-radius:3px}@media (min-width:768px){.color-swatch{width:100px;height:100px}}.color-swatches .gray-darker{background-color:#222}.color-swatches .gray-dark{background-color:#333}.color-swatches .gray{background-color:#555}.color-swatches .gray-light{background-color:#999}.color-swatches .gray-lighter{background-color:#eee}.color-swatches .brand-primary{background-color:#337ab7}.color-swatches .brand-success{background-color:#5cb85c}.color-swatches .brand-warning{background-color:#f0ad4e}.color-swatches .brand-danger{background-color:#d9534f}.color-swatches .brand-info{background-color:#5bc0de}.color-swatches .bs-purple{background-color:#563d7c}.color-swatches .bs-purple-light{background-color:#c7bfd3}.color-swatches .bs-purple-lighter{background-color:#e5e1ea}.color-swatches .bs-gray{background-color:#f9f9f9}.bs-team .team-member{line-height:32px;color:#555}.bs-team .team-member:hover{color:#333;text-decoration:none}.bs-team .github-btn{float:right;width:180px;height:20px;margin-top:6px}.bs-team img{float:left;width:32px;margin-right:10px;border-radius:4px}.bs-docs-browser-bugs td p{margin-bottom:0}.bs-docs-browser-bugs th:first-child{width:18%}.show-grid{margin-bottom:15px}.show-grid [class^=col-]{padding-top:10px;padding-bottom:10px;background-color:#eee;background-color:rgba(86,61,124,.15);border:1px solid #ddd;border:1px solid rgba(86,61,124,.2)}.bs-example{position:relative;padding:45px 15px 15px;margin:0 -15px 15px;border-color:#e5e5e5 #eee #eee;border-style:solid;border-width:1px 0;-webkit-box-shadow:inset 0 3px 6px rgba(0,0,0,.05);box-shadow:inset 0 3px 6px rgba(0,0,0,.05)}.bs-example:after{position:absolute;top:15px;left:15px;font-size:12px;font-weight:700;color:#959595;text-transform:uppercase;letter-spacing:1px;content:"Example"}.bs-example-padded-bottom{padding-bottom:24px}.bs-example+.highlight,.bs-example+.zero-clipboard+.highlight{margin:-15px -15px 15px;border-width:0 0 1px;border-radius:0}@media (min-width:768px){.bs-example{margin-right:0;margin-left:0;background-color:#fff;border-color:#ddd;border-width:1px;border-radius:4px 4px 0 0;-webkit-box-shadow:none;box-shadow:none}.bs-example+.highlight,.bs-example+.zero-clipboard+.highlight{margin-top:-16px;margin-right:0;margin-left:0;border-width:1px;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.bs-example-standalone{border-radius:4px}}.bs-example .container{width:auto}.bs-example>.alert:last-child,.bs-example>.form-control:last-child,.bs-example>.jumbotron:last-child,.bs-example>.list-group:last-child,.bs-example>.navbar:last-child,.bs-example>.panel:last-child,.bs-example>.progress:last-child,.bs-example>.table-responsive:last-child>.table,.bs-example>.table:last-child,.bs-example>.well:last-child,.bs-example>blockquote:last-child,.bs-example>ol:last-child,.bs-example>p:last-child,.bs-example>ul:last-child{margin-bottom:0}.bs-example>p>.close{float:none}.bs-example-type .table .type-info{color:#767676;vertical-align:middle}.bs-example-type .table td{padding:15px 0;border-color:#eee}.bs-example-type .table tr:first-child td{border-top:0}.bs-example-type h1,.bs-example-type h2,.bs-example-type h3,.bs-example-type h4,.bs-example-type h5,.bs-example-type h6{margin:0}.bs-example-bg-classes p{padding:15px}.bs-example>.img-circle,.bs-example>.img-rounded,.bs-example>.img-thumbnail{margin:5px}.bs-example>.table-responsive>.table{background-color:#fff}.bs-example>.btn,.bs-example>.btn-group{margin-top:5px;margin-bottom:5px}.bs-example>.btn-toolbar+.btn-toolbar{margin-top:10px}.bs-example-control-sizing input[type=text]+input[type=text],.bs-example-control-sizing select{margin-top:10px}.bs-example-form .input-group{margin-bottom:10px}.bs-example>textarea.form-control{resize:vertical}.bs-example>.list-group{max-width:400px}.bs-example .navbar:last-child{margin-bottom:0}.bs-navbar-bottom-example,.bs-navbar-top-example{z-index:1;padding:0;overflow:hidden}.bs-navbar-bottom-example .navbar-header,.bs-navbar-top-example .navbar-header{margin-left:0}.bs-navbar-bottom-example .navbar-fixed-bottom,.bs-navbar-top-example .navbar-fixed-top{position:relative;margin-right:0;margin-left:0}.bs-navbar-top-example{padding-bottom:45px}.bs-navbar-top-example:after{top:auto;bottom:15px}.bs-navbar-top-example .navbar-fixed-top{top:-1px}.bs-navbar-bottom-example{padding-top:45px}.bs-navbar-bottom-example .navbar-fixed-bottom{bottom:-1px}.bs-navbar-bottom-example .navbar{margin-bottom:0}@media (min-width:768px){.bs-navbar-bottom-example .navbar-fixed-bottom,.bs-navbar-top-example .navbar-fixed-top{position:absolute}}.bs-example .pagination{margin-top:10px;margin-bottom:10px}.bs-example>.pager{margin-top:0}.bs-example-modal{background-color:#f5f5f5}.bs-example-modal .modal{position:relative;top:auto;right:auto;bottom:auto;left:auto;z-index:1;display:block}.bs-example-modal .modal-dialog{left:auto;margin-right:auto;margin-left:auto}.bs-example>.dropdown>.dropdown-toggle{float:left}.bs-example>.dropdown>.dropdown-menu{position:static;display:block;margin-bottom:5px;clear:left}.bs-example-tabs .nav-tabs{margin-bottom:15px}.bs-example-tooltips{text-align:center}.bs-example-tooltips>.btn{margin-top:5px;margin-bottom:5px}.bs-example-tooltip .tooltip{position:relative;display:inline-block;margin:10px 20px;opacity:1}.bs-example-popover{padding-bottom:24px;background-color:#f9f9f9}.bs-example-popover .popover{position:relative;display:block;float:left;width:260px;margin:20px}.scrollspy-example{position:relative;height:200px;margin-top:10px;overflow:auto}.bs-example>.nav-pills-stacked-example{max-width:300px}#collapseExample .well{margin-bottom:0}.bs-events-table>tbody>tr>td:first-child,.bs-events-table>thead>tr>th:first-child{white-space:nowrap}.bs-events-table>thead>tr>th:first-child{width:150px}.js-options-table>thead>tr>th:nth-child(1),.js-options-table>thead>tr>th:nth-child(2){width:100px}.js-options-table>thead>tr>th:nth-child(3){width:50px}.highlight{padding:9px 14px;margin-bottom:14px;background-color:#f7f7f9;border:1px solid #e1e1e8;border-radius:4px}.highlight pre{padding:0;margin-top:0;margin-bottom:0;word-break:normal;white-space:nowrap;background-color:transparent;border:0}.highlight pre code{font-size:inherit;color:#333}.highlight pre code:first-child{display:inline-block;padding-right:45px}.table-responsive .highlight pre{white-space:normal}.bs-table th small,.responsive-utilities th small{display:block;font-weight:400;color:#999}.responsive-utilities tbody th{font-weight:400}.responsive-utilities td{text-align:center}.responsive-utilities td.is-visible{color:#468847;background-color:#dff0d8!important}.responsive-utilities td.is-hidden{color:#ccc;background-color:#f9f9f9!important}.responsive-utilities-test{margin-top:5px}.responsive-utilities-test .col-xs-6{margin-bottom:10px}.responsive-utilities-test span{display:block;padding:15px 10px;font-size:14px;font-weight:700;line-height:1.1;text-align:center;border-radius:4px}.hidden-on .col-xs-6 .hidden-lg,.hidden-on .col-xs-6 .hidden-md,.hidden-on .col-xs-6 .hidden-sm,.hidden-on .col-xs-6 .hidden-xs,.visible-on .col-xs-6 .hidden-lg,.visible-on .col-xs-6 .hidden-md,.visible-on .col-xs-6 .hidden-sm,.visible-on .col-xs-6 .hidden-xs{color:#999;border:1px solid #ddd}.hidden-on .col-xs-6 .visible-lg-block,.hidden-on .col-xs-6 .visible-md-block,.hidden-on .col-xs-6 .visible-sm-block,.hidden-on .col-xs-6 .visible-xs-block,.visible-on .col-xs-6 .visible-lg-block,.visible-on .col-xs-6 .visible-md-block,.visible-on .col-xs-6 .visible-sm-block,.visible-on .col-xs-6 .visible-xs-block{color:#468847;background-color:#dff0d8;border:1px solid #d6e9c6}.bs-glyphicons{margin:0 -10px 20px;overflow:hidden}.bs-glyphicons-list{padding-left:0;list-style:none}.bs-glyphicons li{float:left;width:25%;height:115px;padding:10px;font-size:10px;line-height:1.4;text-align:center;background-color:#f9f9f9;border:1px solid #fff}.bs-glyphicons .glyphicon{margin-top:5px;margin-bottom:10px;font-size:24px}.bs-glyphicons .glyphicon-class{display:block;text-align:center;word-wrap:break-word}.bs-glyphicons li:hover{color:#fff;background-color:#563d7c}@media (min-width:768px){.bs-glyphicons{margin-right:0;margin-left:0}.bs-glyphicons li{width:12.5%;font-size:12px}}.bs-customizer .toggle{float:right;margin-top:25px}.bs-customizer label{margin-top:10px;font-weight:500;color:#555}.bs-customizer h2{padding-top:30px;margin-top:0;margin-bottom:5px}.bs-customizer h3{margin-bottom:0}.bs-customizer h4{margin-top:15px;margin-bottom:0}.bs-customizer .bs-callout h4{margin-top:0;margin-bottom:5px}.bs-customizer input[type=text]{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;background-color:#fafafa}.bs-customizer .help-block{margin-bottom:5px;font-size:12px}#less-section label{font-weight:400}.bs-customize-download .btn-outline{padding:20px}.bs-customizer-alert{position:fixed;top:0;right:0;left:0;z-index:1030;padding:15px 0;color:#fff;background-color:#d9534f;border-bottom:1px solid #b94441;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25);box-shadow:inset 0 1px 0 rgba(255,255,255,.25)}.bs-customizer-alert .close{margin-top:-4px;font-size:24px}.bs-customizer-alert p{margin-bottom:0}.bs-customizer-alert .glyphicon{margin-right:5px}.bs-customizer-alert pre{margin:10px 0 0;color:#fff;background-color:#a83c3a;border-color:#973634;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 2px 4px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.bs-dropzone{position:relative;padding:20px;margin-bottom:20px;color:#777;text-align:center;border:2px dashed #eee;border-radius:4px}.bs-dropzone .import-header{margin-bottom:5px}.bs-dropzone .glyphicon-download-alt{font-size:40px}.bs-dropzone hr{width:100px}.bs-dropzone .lead{margin-bottom:10px;font-weight:400;color:#333}#import-manual-trigger{cursor:pointer}.bs-dropzone p:last-child{margin-bottom:0}.bs-brand-logos{display:table;width:100%;margin-bottom:15px;overflow:hidden;color:#563d7c;background-color:#f9f9f9;border-radius:4px}.bs-brand-item{padding:60px 0;text-align:center}.bs-brand-item+.bs-brand-item{border-top:1px solid #fff}.bs-brand-logos .inverse{color:#fff;background-color:#563d7c}.bs-brand-item h1,.bs-brand-item h3{margin-top:0;margin-bottom:0}.bs-brand-item .bs-docs-booticon{margin-right:auto;margin-left:auto}.bs-brand-item .glyphicon{width:30px;height:30px;margin:10px auto -10px;line-height:30px;color:#fff;border-radius:50%}.bs-brand-item .glyphicon-ok{background-color:#5cb85c}.bs-brand-item .glyphicon-remove{background-color:#d9534f}@media (min-width:768px){.bs-brand-item{display:table-cell;width:1%}.bs-brand-item+.bs-brand-item{border-top:0;border-left:1px solid #fff}.bs-brand-item h1{font-size:60px}}.zero-clipboard{position:relative;display:none}.btn-clipboard{position:absolute;top:0;right:0;z-index:10;display:block;padding:5px 8px;font-size:12px;color:#767676;cursor:pointer;background-color:#fff;border:1px solid #e1e1e8;border-radius:0 4px 0 4px}.btn-clipboard-hover{color:#fff;background-color:#563d7c;border-color:#563d7c}@media (min-width:768px){.zero-clipboard{display:block}.bs-example+.zero-clipboard .btn-clipboard{top:-16px;border-top-right-radius:0}}.anchorjs-link{color:inherit}@media (max-width:480px){.anchorjs-link{display:none}}:hover>.anchorjs-link{opacity:.75;-webkit-transition:color .16s linear;-o-transition:color .16s linear;transition:color .16s linear}.anchorjs-link:focus,:hover>.anchorjs-link:hover{text-decoration:none;opacity:1}#focusedInput{border-color:#ccc;border-color:rgba(82,168,236,.8);outline:0;outline:thin dotted\9;-webkit-box-shadow:0 0 8px rgba(82,168,236,.6);box-shadow:0 0 8px rgba(82,168,236,.6)} \ No newline at end of file diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/docs.css b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/docs.css new file mode 100644 index 0000000..622b3e5 --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/docs.css @@ -0,0 +1,1638 @@ +/*! + * Bootstrap Docs (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under the Creative Commons Attribution 3.0 Unported License. For + * details, see https://creativecommons.org/licenses/by/3.0/. + */ + + +/* + * Bootstrap Documentation + * Special styles for presenting Bootstrap's documentation and code examples. + */ + + +/* + * Scaffolding + * + * Update the basics of our documents to prep for docs content. + */ + +body { + position: relative; /* For scrollspy */ +} + +/* Keep code small in tables on account of limited space */ +.table code { + font-size: 13px; + font-weight: normal; +} + +/* Inline code within headings retain the heading's background-color */ +h2 code, +h3 code, +h4 code { + background-color: inherit; +} + +/* Outline button for use within the docs */ +.btn-outline { + color: #563d7c; + background-color: transparent; + border-color: #563d7c; +} +.btn-outline:hover, +.btn-outline:focus, +.btn-outline:active { + color: #fff; + background-color: #563d7c; + border-color: #563d7c; +} + +/* Inverted outline button (white on dark) */ +.btn-outline-inverse { + color: #fff; + background-color: transparent; + border-color: #cdbfe3; +} +.btn-outline-inverse:hover, +.btn-outline-inverse:focus, +.btn-outline-inverse:active { + color: #563d7c; + text-shadow: none; + background-color: #fff; + border-color: #fff; +} + +/* Bootstrap "B" icon */ +.bs-docs-booticon { + display: block; + font-weight: 500; + color: #fff; + text-align: center; + cursor: default; + background-color: #563d7c; + border-radius: 15%; +} +.bs-docs-booticon-sm { + width: 30px; + height: 30px; + font-size: 20px; + line-height: 28px; +} +.bs-docs-booticon-lg { + width: 144px; + height: 144px; + font-size: 108px; + line-height: 140px; +} +.bs-docs-booticon-inverse { + color: #563d7c; + background-color: #fff; +} +.bs-docs-booticon-outline { + background-color: transparent; + border: 1px solid #cdbfe3; +} + + +/* + * Fancy skip link + * + * Make it look a bit less "bare bones" + * Also includes focus suppression for the Chrome tabindex="-1" workaround + */ + +#skippy { + display: block; + padding: 1em; + color: #fff; + background-color: #6f5499; + outline: 0; +} + +#skippy .skiplink-text { + padding: .5em; + outline: 1px dotted; +} + +#content:focus { + outline: none; +} + + +/* + * Main navigation + * + * Turn the `.navbar` at the top of the docs purple. + */ + +.bs-docs-nav { + margin-bottom: 0; + background-color: #fff; + border-bottom: 0; +} +.bs-home-nav .bs-nav-b { + display: none; +} +.bs-docs-nav .navbar-brand, +.bs-docs-nav .navbar-nav > li > a { + font-weight: 500; + color: #563d7c; +} +.bs-docs-nav .navbar-nav > li > a:hover, +.bs-docs-nav .navbar-nav > .active > a, +.bs-docs-nav .navbar-nav > .active > a:hover { + color: #463265; + background-color: #f9f9f9; +} +.bs-docs-nav .navbar-toggle .icon-bar { + background-color: #563d7c; +} +.bs-docs-nav .navbar-header .navbar-toggle { + border-color: #fff; +} +.bs-docs-nav .navbar-header .navbar-toggle:hover, +.bs-docs-nav .navbar-header .navbar-toggle:focus { + background-color: #f9f9f9; + border-color: #f9f9f9; +} + + +/* + * Footer + * + * Separated section of content at the bottom of all pages, save the homepage. + */ + +.bs-docs-footer { + padding-top: 40px; + padding-bottom: 40px; + margin-top: 100px; + color: #767676; + text-align: center; + border-top: 1px solid #e5e5e5; +} +.bs-docs-footer-links { + padding-left: 0; + margin-top: 20px; +} +.bs-docs-footer-links li { + display: inline; + padding: 0 2px; +} +.bs-docs-footer-links li:first-child { + padding-left: 0; +} + +@media (min-width: 768px) { + .bs-docs-footer p { + margin-bottom: 0; + } +} + + +/* + * Social buttons + * + * Twitter and GitHub social action buttons (for homepage and footer). + */ + +.bs-docs-social { + margin-bottom: 20px; + text-align: center; +} +.bs-docs-social-buttons { + display: inline-block; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.bs-docs-social-buttons li { + display: inline-block; + padding: 5px 8px; + line-height: 1; +} +.bs-docs-social-buttons .twitter-follow-button { + width: 225px !important; +} +.bs-docs-social-buttons .twitter-share-button { + width: 98px !important; +} +/* Style the GitHub buttons via CSS instead of inline attributes */ +.github-btn { + overflow: hidden; + border: 0; +} + + +/* + * Homepage + * + * Tweaks to the custom homepage and the masthead (main jumbotron). + */ + +/* Share masthead with page headers */ +.bs-docs-masthead, +.bs-docs-header { + position: relative; + padding: 30px 0; + color: #cdbfe3; + text-align: center; + text-shadow: 0 1px 0 rgba(0,0,0,.1); + background-color: #6f5499; + background-image: -webkit-gradient(linear, left top, left bottom, from(#563d7c), to(#6f5499)); + background-image: -webkit-linear-gradient(top, #563d7c 0%, #6f5499 100%); + background-image: -o-linear-gradient(top, #563d7c 0%, #6f5499 100%); + background-image: linear-gradient(to bottom, #563d7c 0%, #6f5499 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#563d7c', endColorstr='#6F5499', GradientType=0); + background-repeat: repeat-x; +} + +/* Masthead (headings and download button) */ +.bs-docs-masthead .bs-docs-booticon { + margin: 0 auto 30px; +} +.bs-docs-masthead h1 { + font-weight: 300; + line-height: 1; + color: #fff; +} +.bs-docs-masthead .lead { + margin: 0 auto 30px; + font-size: 20px; + color: #fff; +} +.bs-docs-masthead .version { + margin-top: -15px; + margin-bottom: 30px; + color: #9783b9; +} +.bs-docs-masthead .btn { + width: 100%; + padding: 15px 30px; + font-size: 20px; +} + +@media (min-width: 480px) { + .bs-docs-masthead .btn { + width: auto; + } +} + +@media (min-width: 768px) { + .bs-docs-masthead { + padding: 80px 0; + } + .bs-docs-masthead h1 { + font-size: 60px; + } + .bs-docs-masthead .lead { + font-size: 24px; + } +} + +@media (min-width: 992px) { + .bs-docs-masthead .lead { + width: 80%; + font-size: 30px; + } +} + + +/* + * Page headers + * + * Jumbotron-esque headers at the top of every page that's not the homepage. + */ + +/* Page headers */ +.bs-docs-header { + margin-bottom: 40px; + font-size: 20px; +} +.bs-docs-header h1 { + margin-top: 0; + color: #fff; +} +.bs-docs-header p { + margin-bottom: 0; + font-weight: 300; + line-height: 1.4; +} +.bs-docs-header .container { + position: relative; +} + +@media (min-width: 768px) { + .bs-docs-header { + padding-top: 60px; + padding-bottom: 60px; + font-size: 24px; + text-align: left; + } + .bs-docs-header h1 { + font-size: 60px; + line-height: 1; + } +} + +@media (min-width: 992px) { + .bs-docs-header h1, + .bs-docs-header p { + margin-right: 380px; + } +} + + +/* + * Carbon ads + * + * Single display ad that shows on all pages (except homepage) in page headers. + * The hella `!important` is required for any pre-set property. + */ + +.carbonad { + width: auto !important; + height: auto !important; + padding: 20px !important; + margin: 30px -15px -31px !important; + overflow: hidden; /* clearfix */ + font-size: 13px !important; + line-height: 16px !important; + text-align: left; + background: transparent !important; + border: solid #866ab3 !important; + border-width: 1px 0 !important; +} +.carbonad-img { + margin: 0 !important; +} +.carbonad-text, +.carbonad-tag { + display: block !important; + float: none !important; + width: auto !important; + height: auto !important; + margin-left: 145px !important; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important; +} +.carbonad-text { + padding-top: 0 !important; +} +.carbonad-tag { + color: inherit !important; + text-align: left !important; +} +.carbonad-text a, +.carbonad-tag a { + color: #fff !important; +} +.carbonad #azcarbon > img { + display: none; /* hide what I assume are tracking images */ +} + +@media (min-width: 480px) { + .carbonad { + width: 330px !important; + margin: 20px auto !important; + border-width: 1px !important; + border-radius: 4px; + } + .bs-docs-masthead .carbonad { + margin: 50px auto 0 !important; + } +} + +@media (min-width: 768px) { + .carbonad { + margin-right: 0 !important; + margin-left: 0 !important; + } +} + +@media (min-width: 992px) { + .carbonad { + position: absolute; + top: 0; + right: 15px; /* 15px instead of 0 since box-sizing */ + width: 330px !important; + padding: 15px !important; + margin: 0 !important; + } + .bs-docs-masthead .carbonad { + position: static; + } +} + + +/* + * Homepage featurettes + * + * Reasons to use Bootstrap, entries from the Expo, and more. + */ + +.bs-docs-featurette { + padding-top: 40px; + padding-bottom: 40px; + font-size: 16px; + line-height: 1.5; + color: #555; + text-align: center; + background-color: #fff; + border-bottom: 1px solid #e5e5e5; +} +.bs-docs-featurette + .bs-docs-footer { + margin-top: 0; + border-top: 0; +} + +.bs-docs-featurette-title { + margin-bottom: 5px; + font-size: 30px; + font-weight: normal; + color: #333; +} +.half-rule { + width: 100px; + margin: 40px auto; +} +.bs-docs-featurette h3 { + margin-bottom: 5px; + font-weight: normal; + color: #333; +} +.bs-docs-featurette-img { + display: block; + margin-bottom: 20px; + color: #333; +} +.bs-docs-featurette-img:hover { + color: #337ab7; + text-decoration: none; +} +.bs-docs-featurette-img img { + display: block; + margin-bottom: 15px; +} + +@media (min-width: 480px) { + .bs-docs-featurette .img-responsive { + margin-top: 30px; + } +} +@media (min-width: 768px) { + .bs-docs-featurette { + padding-top: 100px; + padding-bottom: 100px; + } + .bs-docs-featurette-title { + font-size: 40px; + } + .bs-docs-featurette .lead { + max-width: 80%; + margin-right: auto; + margin-left: auto; + } + .bs-docs-featurette .img-responsive { + margin-top: 0; + } +} + + +/* + * Featured sites + * + * Homepage thumbnails from the Expo. + */ + +.bs-docs-featured-sites { + margin-right: -1px; + margin-left: -1px; +} +.bs-docs-featured-sites .col-xs-6 { + padding: 1px; +} +.bs-docs-featured-sites .img-responsive { + margin-top: 0; +} + +@media (min-width: 768px) { + .bs-docs-featured-sites .col-sm-3:first-child img { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + .bs-docs-featured-sites .col-sm-3:last-child img { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + } +} + + +/* + * Examples + * + * Linked docs examples. + */ + +.bs-examples .thumbnail { + margin-bottom: 10px; +} +.bs-examples h4 { + margin-bottom: 5px; +} +.bs-examples p { + margin-bottom: 20px; +} + +@media (max-width: 480px) { + .bs-examples { + margin-right: -10px; + margin-left: -10px; + } + .bs-examples > [class^="col-"] { + padding-right: 10px; + padding-left: 10px; + } +} + + +/* + * Side navigation + * + * Scrollspy and affixed enhanced navigation to highlight sections and secondary + * sections of docs content. + */ + +/* By default it's not affixed in mobile views, so undo that */ +.bs-docs-sidebar.affix { + position: static; +} +@media (min-width: 768px) { + .bs-docs-sidebar { + padding-left: 20px; + } +} + +/* First level of nav */ +.bs-docs-sidenav { + margin-top: 20px; + margin-bottom: 20px; +} + +/* All levels of nav */ +.bs-docs-sidebar .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +.bs-docs-sidebar .nav > li > a:hover, +.bs-docs-sidebar .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +.bs-docs-sidebar .nav > .active > a, +.bs-docs-sidebar .nav > .active:hover > a, +.bs-docs-sidebar .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +.bs-docs-sidebar .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +.bs-docs-sidebar .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +.bs-docs-sidebar .nav .nav > li > a:hover, +.bs-docs-sidebar .nav .nav > li > a:focus { + padding-left: 29px; +} +.bs-docs-sidebar .nav .nav > .active > a, +.bs-docs-sidebar .nav .nav > .active:hover > a, +.bs-docs-sidebar .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* Back to top (hidden on mobile) */ +.back-to-top, +.bs-docs-theme-toggle { + display: none; + padding: 4px 10px; + margin-top: 10px; + margin-left: 10px; + font-size: 12px; + font-weight: 500; + color: #999; +} +.back-to-top:hover, +.bs-docs-theme-toggle:hover { + color: #563d7c; + text-decoration: none; +} +.bs-docs-theme-toggle { + margin-top: 0; +} + +@media (min-width: 768px) { + .back-to-top, + .bs-docs-theme-toggle { + display: block; + } +} + +/* Show and affix the side nav when space allows it */ +@media (min-width: 992px) { + .bs-docs-sidebar .nav > .active > ul { + display: block; + } + /* Widen the fixed sidebar */ + .bs-docs-sidebar.affix, + .bs-docs-sidebar.affix-bottom { + width: 213px; + } + .bs-docs-sidebar.affix { + position: fixed; /* Undo the static from mobile first approach */ + top: 20px; + } + .bs-docs-sidebar.affix-bottom { + position: absolute; /* Undo the static from mobile first approach */ + } + .bs-docs-sidebar.affix-bottom .bs-docs-sidenav, + .bs-docs-sidebar.affix .bs-docs-sidenav { + margin-top: 0; + margin-bottom: 0; + } +} +@media (min-width: 1200px) { + /* Widen the fixed sidebar again */ + .bs-docs-sidebar.affix-bottom, + .bs-docs-sidebar.affix { + width: 263px; + } +} + + +/* + * Docs sections + * + * Content blocks for each component or feature. + */ + +/* Space things out */ +.bs-docs-section { + margin-bottom: 60px; +} +.bs-docs-section:last-child { + margin-bottom: 0; +} + +h1[id] { + padding-top: 20px; + margin-top: 0; +} + + +/* + * Callouts + * + * Not quite alerts, but custom and helpful notes for folks reading the docs. + * Requires a base and modifier class. + */ + +/* Common styles for all types */ +.bs-callout { + padding: 20px; + margin: 20px 0; + border: 1px solid #eee; + border-left-width: 5px; + border-radius: 3px; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} +.bs-callout code { + border-radius: 3px; +} + +/* Tighten up space between multiple callouts */ +.bs-callout + .bs-callout { + margin-top: -5px; +} + +/* Variations */ +.bs-callout-danger { + border-left-color: #ce4844; +} +.bs-callout-danger h4 { + color: #ce4844; +} +.bs-callout-warning { + border-left-color: #aa6708; +} +.bs-callout-warning h4 { + color: #aa6708; +} +.bs-callout-info { + border-left-color: #1b809e; +} +.bs-callout-info h4 { + color: #1b809e; +} + + +/* + * Color swatches + * + * Color swatches and associated values for our grayscale and brand colors. + */ + +.color-swatches { + margin: 0 -5px; + overflow: hidden; /* clearfix */ +} +.color-swatch { + float: left; + width: 60px; + height: 60px; + margin: 0 5px; + border-radius: 3px; +} + +@media (min-width: 768px) { + .color-swatch { + width: 100px; + height: 100px; + } +} + +/* Framework colors */ +.color-swatches .gray-darker { + background-color: #222; +} +.color-swatches .gray-dark { + background-color: #333; +} +.color-swatches .gray { + background-color: #555; +} +.color-swatches .gray-light { + background-color: #999; +} +.color-swatches .gray-lighter { + background-color: #eee; +} +.color-swatches .brand-primary { + background-color: #337ab7; +} +.color-swatches .brand-success { + background-color: #5cb85c; +} +.color-swatches .brand-warning { + background-color: #f0ad4e; +} +.color-swatches .brand-danger { + background-color: #d9534f; +} +.color-swatches .brand-info { + background-color: #5bc0de; +} + +/* Docs colors */ +.color-swatches .bs-purple { + background-color: #563d7c; +} +.color-swatches .bs-purple-light { + background-color: #c7bfd3; +} +.color-swatches .bs-purple-lighter { + background-color: #e5e1ea; +} +.color-swatches .bs-gray { + background-color: #f9f9f9; +} + + +/* + * Team members + * + * Avatars, names, and usernames for core team. + */ + +.bs-team .team-member { + line-height: 32px; + color: #555; +} +.bs-team .team-member:hover { + color: #333; + text-decoration: none; +} +.bs-team .github-btn { + float: right; + width: 180px; + height: 20px; + margin-top: 6px; +} +.bs-team img { + float: left; + width: 32px; + margin-right: 10px; + border-radius: 4px; +} + + +/* + * Wall of Browser Bugs + * + * Better display for the responsive table on the Wall of Browser Bugs. + */ + +.bs-docs-browser-bugs td p { + margin-bottom: 0; +} + +.bs-docs-browser-bugs th:first-child { + width: 18%; +} + + +/* + * Grid examples + * + * Highlight the grid columns within the docs so folks can see their padding, + * alignment, sizing, etc. + */ + +.show-grid { + margin-bottom: 15px; +} +.show-grid [class^="col-"] { + padding-top: 10px; + padding-bottom: 10px; + background-color: #eee; + background-color: rgba(86,61,124,.15); + border: 1px solid #ddd; + border: 1px solid rgba(86,61,124,.2); +} + + +/* + * Examples + * + * Isolated sections of example content for each component or feature. Usually + * followed by a code snippet. + */ + +.bs-example { + position: relative; + padding: 45px 15px 15px; + margin: 0 -15px 15px; + border-color: #e5e5e5 #eee #eee; + border-style: solid; + border-width: 1px 0; + -webkit-box-shadow: inset 0 3px 6px rgba(0,0,0,.05); + box-shadow: inset 0 3px 6px rgba(0,0,0,.05); +} +/* Echo out a label for the example */ +.bs-example:after { + position: absolute; + top: 15px; + left: 15px; + font-size: 12px; + font-weight: bold; + color: #959595; + text-transform: uppercase; + letter-spacing: 1px; + content: "Example"; +} + +.bs-example-padded-bottom { + padding-bottom: 24px; +} + +/* Tweak display of the code snippets when following an example */ +.bs-example + .highlight, +.bs-example + .zero-clipboard + .highlight { + margin: -15px -15px 15px; + border-width: 0 0 1px; + border-radius: 0; +} + +/* Make the examples and snippets not full-width */ +@media (min-width: 768px) { + .bs-example { + margin-right: 0; + margin-left: 0; + background-color: #fff; + border-color: #ddd; + border-width: 1px; + border-radius: 4px 4px 0 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .bs-example + .highlight, + .bs-example + .zero-clipboard + .highlight { + margin-top: -16px; + margin-right: 0; + margin-left: 0; + border-width: 1px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + } + .bs-example-standalone { + border-radius: 4px; + } +} + +/* Undo width of container */ +.bs-example .container { + width: auto; +} + +/* Tweak content of examples for optimum awesome */ +.bs-example > p:last-child, +.bs-example > ul:last-child, +.bs-example > ol:last-child, +.bs-example > blockquote:last-child, +.bs-example > .form-control:last-child, +.bs-example > .table:last-child, +.bs-example > .navbar:last-child, +.bs-example > .jumbotron:last-child, +.bs-example > .alert:last-child, +.bs-example > .panel:last-child, +.bs-example > .list-group:last-child, +.bs-example > .well:last-child, +.bs-example > .progress:last-child, +.bs-example > .table-responsive:last-child > .table { + margin-bottom: 0; +} +.bs-example > p > .close { + float: none; +} + +/* Typography */ +.bs-example-type .table .type-info { + color: #767676; + vertical-align: middle; +} +.bs-example-type .table td { + padding: 15px 0; + border-color: #eee; +} +.bs-example-type .table tr:first-child td { + border-top: 0; +} +.bs-example-type h1, +.bs-example-type h2, +.bs-example-type h3, +.bs-example-type h4, +.bs-example-type h5, +.bs-example-type h6 { + margin: 0; +} + +/* Contextual background colors */ +.bs-example-bg-classes p { + padding: 15px; +} + +/* Images */ +.bs-example > .img-circle, +.bs-example > .img-rounded, +.bs-example > .img-thumbnail { + margin: 5px; +} + +/* Tables */ +.bs-example > .table-responsive > .table { + background-color: #fff; +} + +/* Buttons */ +.bs-example > .btn, +.bs-example > .btn-group { + margin-top: 5px; + margin-bottom: 5px; +} +.bs-example > .btn-toolbar + .btn-toolbar { + margin-top: 10px; +} + +/* Forms */ +.bs-example-control-sizing select, +.bs-example-control-sizing input[type="text"] + input[type="text"] { + margin-top: 10px; +} +.bs-example-form .input-group { + margin-bottom: 10px; +} +.bs-example > textarea.form-control { + resize: vertical; +} + +/* List groups */ +.bs-example > .list-group { + max-width: 400px; +} + +/* Navbars */ +.bs-example .navbar:last-child { + margin-bottom: 0; +} +.bs-navbar-top-example, +.bs-navbar-bottom-example { + z-index: 1; + padding: 0; + overflow: hidden; /* cut the drop shadows off */ +} +.bs-navbar-top-example .navbar-header, +.bs-navbar-bottom-example .navbar-header { + margin-left: 0; +} +.bs-navbar-top-example .navbar-fixed-top, +.bs-navbar-bottom-example .navbar-fixed-bottom { + position: relative; + margin-right: 0; + margin-left: 0; +} +.bs-navbar-top-example { + padding-bottom: 45px; +} +.bs-navbar-top-example:after { + top: auto; + bottom: 15px; +} +.bs-navbar-top-example .navbar-fixed-top { + top: -1px; +} +.bs-navbar-bottom-example { + padding-top: 45px; +} +.bs-navbar-bottom-example .navbar-fixed-bottom { + bottom: -1px; +} +.bs-navbar-bottom-example .navbar { + margin-bottom: 0; +} +@media (min-width: 768px) { + .bs-navbar-top-example .navbar-fixed-top, + .bs-navbar-bottom-example .navbar-fixed-bottom { + position: absolute; + } +} + +/* Pagination */ +.bs-example .pagination { + margin-top: 10px; + margin-bottom: 10px; +} + +/* Pager */ +.bs-example > .pager { + margin-top: 0; +} + +/* Example modals */ +.bs-example-modal { + background-color: #f5f5f5; +} +.bs-example-modal .modal { + position: relative; + top: auto; + right: auto; + bottom: auto; + left: auto; + z-index: 1; + display: block; +} +.bs-example-modal .modal-dialog { + left: auto; + margin-right: auto; + margin-left: auto; +} + +/* Example dropdowns */ +.bs-example > .dropdown > .dropdown-toggle { + float: left; +} +.bs-example > .dropdown > .dropdown-menu { + position: static; + display: block; + margin-bottom: 5px; + clear: left; +} + +/* Example tabbable tabs */ +.bs-example-tabs .nav-tabs { + margin-bottom: 15px; +} + +/* Tooltips */ +.bs-example-tooltips { + text-align: center; +} +.bs-example-tooltips > .btn { + margin-top: 5px; + margin-bottom: 5px; +} +.bs-example-tooltip .tooltip { + position: relative; + display: inline-block; + margin: 10px 20px; + opacity: 1; +} + +/* Popovers */ +.bs-example-popover { + padding-bottom: 24px; + background-color: #f9f9f9; +} +.bs-example-popover .popover { + position: relative; + display: block; + float: left; + width: 260px; + margin: 20px; +} + +/* Scrollspy demo on fixed height div */ +.scrollspy-example { + position: relative; + height: 200px; + margin-top: 10px; + overflow: auto; +} + +.bs-example > .nav-pills-stacked-example { + max-width: 300px; +} + +/* Simple collapse example */ +#collapseExample .well { + margin-bottom: 0; +} + +/* Don't wrap event names in Events tables in JS plugin docs */ +.bs-events-table > thead > tr > th:first-child, +.bs-events-table > tbody > tr > td:first-child { + white-space: nowrap; +} + +.bs-events-table > thead > tr > th:first-child { + width: 150px; +} + +.js-options-table > thead > tr > th:nth-child(1), +.js-options-table > thead > tr > th:nth-child(2) { + width: 100px; +} + +.js-options-table > thead > tr > th:nth-child(3) { + width: 50px; +} + +/* + * Code snippets + * + * Generated via Pygments and Jekyll, these are snippets of HTML, CSS, and JS. + */ + +.highlight { + padding: 9px 14px; + margin-bottom: 14px; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + border-radius: 4px; +} +.highlight pre { + padding: 0; + margin-top: 0; + margin-bottom: 0; + word-break: normal; + white-space: nowrap; + background-color: transparent; + border: 0; +} +.highlight pre code { + font-size: inherit; + color: #333; /* Effectively the base text color */ +} +.highlight pre code:first-child { + display: inline-block; + padding-right: 45px; +} + + +/* + * Responsive tests + * + * Generate a set of tests to show the responsive utilities in action. + */ + +/* Responsive (scrollable) doc tables */ +.table-responsive .highlight pre { + white-space: normal; +} + +/* Utility classes table */ +.bs-table th small, +.responsive-utilities th small { + display: block; + font-weight: normal; + color: #999; +} +.responsive-utilities tbody th { + font-weight: normal; +} +.responsive-utilities td { + text-align: center; +} +.responsive-utilities td.is-visible { + color: #468847; + background-color: #dff0d8 !important; +} +.responsive-utilities td.is-hidden { + color: #ccc; + background-color: #f9f9f9 !important; +} + +/* Responsive tests */ +.responsive-utilities-test { + margin-top: 5px; +} +.responsive-utilities-test .col-xs-6 { + margin-bottom: 10px; +} +.responsive-utilities-test span { + display: block; + padding: 15px 10px; + font-size: 14px; + font-weight: bold; + line-height: 1.1; + text-align: center; + border-radius: 4px; +} +.visible-on .col-xs-6 .hidden-xs, +.visible-on .col-xs-6 .hidden-sm, +.visible-on .col-xs-6 .hidden-md, +.visible-on .col-xs-6 .hidden-lg, +.hidden-on .col-xs-6 .hidden-xs, +.hidden-on .col-xs-6 .hidden-sm, +.hidden-on .col-xs-6 .hidden-md, +.hidden-on .col-xs-6 .hidden-lg { + color: #999; + border: 1px solid #ddd; +} +.visible-on .col-xs-6 .visible-xs-block, +.visible-on .col-xs-6 .visible-sm-block, +.visible-on .col-xs-6 .visible-md-block, +.visible-on .col-xs-6 .visible-lg-block, +.hidden-on .col-xs-6 .visible-xs-block, +.hidden-on .col-xs-6 .visible-sm-block, +.hidden-on .col-xs-6 .visible-md-block, +.hidden-on .col-xs-6 .visible-lg-block { + color: #468847; + background-color: #dff0d8; + border: 1px solid #d6e9c6; +} + + +/* + * Glyphicons + * + * Special styles for displaying the icons and their classes in the docs. + */ + +.bs-glyphicons { + margin: 0 -10px 20px; + overflow: hidden; +} +.bs-glyphicons-list { + padding-left: 0; + list-style: none; +} +.bs-glyphicons li { + float: left; + width: 25%; + height: 115px; + padding: 10px; + font-size: 10px; + line-height: 1.4; + text-align: center; + background-color: #f9f9f9; + border: 1px solid #fff; +} +.bs-glyphicons .glyphicon { + margin-top: 5px; + margin-bottom: 10px; + font-size: 24px; +} +.bs-glyphicons .glyphicon-class { + display: block; + text-align: center; + word-wrap: break-word; /* Help out IE10+ with class names */ +} +.bs-glyphicons li:hover { + color: #fff; + background-color: #563d7c; +} + +@media (min-width: 768px) { + .bs-glyphicons { + margin-right: 0; + margin-left: 0; + } + .bs-glyphicons li { + width: 12.5%; + font-size: 12px; + } +} + + +/* + * Customizer + * + * Since this is so form control heavy, we have quite a few styles to customize + * the display of inputs, headings, and more. Also included are all the download + * buttons and actions. + */ + +.bs-customizer .toggle { + float: right; + margin-top: 25px; +} + +/* Headings and form contrls */ +.bs-customizer label { + margin-top: 10px; + font-weight: 500; + color: #555; +} +.bs-customizer h2 { + padding-top: 30px; + margin-top: 0; + margin-bottom: 5px; +} +.bs-customizer h3 { + margin-bottom: 0; +} +.bs-customizer h4 { + margin-top: 15px; + margin-bottom: 0; +} +.bs-customizer .bs-callout h4 { + margin-top: 0; /* lame, but due to specificity we have to duplicate */ + margin-bottom: 5px; +} +.bs-customizer input[type="text"] { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + background-color: #fafafa; +} +.bs-customizer .help-block { + margin-bottom: 5px; + font-size: 12px; +} + +/* For the variables, use regular weight */ +#less-section label { + font-weight: normal; +} + +/* Downloads */ +.bs-customize-download .btn-outline { + padding: 20px; +} + +/* Error handling */ +.bs-customizer-alert { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; + padding: 15px 0; + color: #fff; + background-color: #d9534f; + border-bottom: 1px solid #b94441; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25); + box-shadow: inset 0 1px 0 rgba(255,255,255,.25); +} +.bs-customizer-alert .close { + margin-top: -4px; + font-size: 24px; +} +.bs-customizer-alert p { + margin-bottom: 0; +} +.bs-customizer-alert .glyphicon { + margin-right: 5px; +} +.bs-customizer-alert pre { + margin: 10px 0 0; + color: #fff; + background-color: #a83c3a; + border-color: #973634; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); + box-shadow: inset 0 2px 4px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); +} + +.bs-dropzone { + position: relative; + padding: 20px; + margin-bottom: 20px; + color: #777; + text-align: center; + border: 2px dashed #eee; + border-radius: 4px; +} +.bs-dropzone .import-header { + margin-bottom: 5px; +} +.bs-dropzone .glyphicon-download-alt { + font-size: 40px; +} +.bs-dropzone hr { + width: 100px; +} +.bs-dropzone .lead { + margin-bottom: 10px; + font-weight: normal; + color: #333; +} +/*.bs-dropzone*/ #import-manual-trigger { + cursor: pointer; +} +.bs-dropzone p:last-child { + margin-bottom: 0; +} + +/* + * Brand guidelines + * + * Extra styles for displaying wordmarks, logos, etc. + */ + +/* Logo series wrapper */ +.bs-brand-logos { + display: table; + width: 100%; + margin-bottom: 15px; + overflow: hidden; + color: #563d7c; + background-color: #f9f9f9; + border-radius: 4px; +} + +/* Individual items */ +.bs-brand-item { + padding: 60px 0; + text-align: center; +} +.bs-brand-item + .bs-brand-item { + border-top: 1px solid #fff; +} +.bs-brand-logos .inverse { + color: #fff; + background-color: #563d7c; +} + +/* Heading content within */ +.bs-brand-item h1, +.bs-brand-item h3 { + margin-top: 0; + margin-bottom: 0; +} +.bs-brand-item .bs-docs-booticon { + margin-right: auto; + margin-left: auto; +} + +/* Make the icons stand out on what is/isn't okay */ +.bs-brand-item .glyphicon { + width: 30px; + height: 30px; + margin: 10px auto -10px; + line-height: 30px; + color: #fff; + border-radius: 50%; +} +.bs-brand-item .glyphicon-ok { + background-color: #5cb85c; +} +.bs-brand-item .glyphicon-remove { + background-color: #d9534f; +} + +@media (min-width: 768px) { + .bs-brand-item { + display: table-cell; + width: 1%; + } + .bs-brand-item + .bs-brand-item { + border-top: 0; + border-left: 1px solid #fff; + } + .bs-brand-item h1 { + font-size: 60px; + } +} + + +/* + * ZeroClipboard styles + */ + +.zero-clipboard { + position: relative; + display: none; +} +.btn-clipboard { + position: absolute; + top: 0; + right: 0; + z-index: 10; + display: block; + padding: 5px 8px; + font-size: 12px; + color: #767676; + cursor: pointer; + background-color: #fff; + border: 1px solid #e1e1e8; + border-radius: 0 4px 0 4px; +} +.btn-clipboard-hover { + color: #fff; + background-color: #563d7c; + border-color: #563d7c; +} + +@media (min-width: 768px) { + .zero-clipboard { + display: block; + } + .bs-example + .zero-clipboard .btn-clipboard { + top: -16px; + border-top-right-radius: 0; + } +} + +/* + * AnchorJS Styles + */ +.anchorjs-link { + color: inherit; +} + +@media (max-width: 480px) { + .anchorjs-link { + display: none; + } +} + +*:hover > .anchorjs-link { + opacity: .75; + -webkit-transition: color .16s linear; + -o-transition: color .16s linear; + transition: color .16s linear; +} + +*:hover > .anchorjs-link:hover, +.anchorjs-link:focus { + text-decoration: none; + opacity: 1; +} + +/* + * Miscellaneous + * + * Odds and ends for optimum docs display. + */ + +/* Pseudo :focus state for showing how it looks in the docs */ +#focusedInput { + border-color: rgb(204,204,204); /* Restate unfocused value to make CSSLint happy that there's a pre-CSS3 fallback*/ + border-color: rgba(82,168,236,.8); + outline: 0; + outline: thin dotted \9; /* IE6-9 */ + -webkit-box-shadow: 0 0 8px rgba(82,168,236,.6); + box-shadow: 0 0 8px rgba(82,168,236,.6); +} diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/pygments-manni.css b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/pygments-manni.css new file mode 100644 index 0000000..1b3c92c --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/css/src/pygments-manni.css @@ -0,0 +1,66 @@ +.hll { background-color: #ffffcc } + /*{ background: #f0f3f3; }*/ +.c { color: #999; } /* Comment */ +.err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.k { color: #006699; } /* Keyword */ +.o { color: #555555 } /* Operator */ +.cm { color: #999; } /* Comment.Multiline */ /* Edited to remove italics and make into comment */ +.cp { color: #009999 } /* Comment.Preproc */ +.c1 { color: #999; } /* Comment.Single */ +.cs { color: #999; } /* Comment.Special */ +.gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.ge { font-style: italic } /* Generic.Emph */ +.gr { color: #FF0000 } /* Generic.Error */ +.gh { color: #003300; } /* Generic.Heading */ +.gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.go { color: #AAAAAA } /* Generic.Output */ +.gp { color: #000099; } /* Generic.Prompt */ +.gs { } /* Generic.Strong */ +.gu { color: #003300; } /* Generic.Subheading */ +.gt { color: #99CC66 } /* Generic.Traceback */ +.kc { color: #006699; } /* Keyword.Constant */ +.kd { color: #006699; } /* Keyword.Declaration */ +.kn { color: #006699; } /* Keyword.Namespace */ +.kp { color: #006699 } /* Keyword.Pseudo */ +.kr { color: #006699; } /* Keyword.Reserved */ +.kt { color: #007788; } /* Keyword.Type */ +.m { color: #FF6600 } /* Literal.Number */ +.s { color: #d44950 } /* Literal.String */ +.na { color: #4f9fcf } /* Name.Attribute */ +.nb { color: #336666 } /* Name.Builtin */ +.nc { color: #00AA88; } /* Name.Class */ +.no { color: #336600 } /* Name.Constant */ +.nd { color: #9999FF } /* Name.Decorator */ +.ni { color: #999999; } /* Name.Entity */ +.ne { color: #CC0000; } /* Name.Exception */ +.nf { color: #CC00FF } /* Name.Function */ +.nl { color: #9999FF } /* Name.Label */ +.nn { color: #00CCFF; } /* Name.Namespace */ +.nt { color: #2f6f9f; } /* Name.Tag */ +.nv { color: #003333 } /* Name.Variable */ +.ow { color: #000000; } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #FF6600 } /* Literal.Number.Float */ +.mh { color: #FF6600 } /* Literal.Number.Hex */ +.mi { color: #FF6600 } /* Literal.Number.Integer */ +.mo { color: #FF6600 } /* Literal.Number.Oct */ +.sb { color: #CC3300 } /* Literal.String.Backtick */ +.sc { color: #CC3300 } /* Literal.String.Char */ +.sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.s2 { color: #CC3300 } /* Literal.String.Double */ +.se { color: #CC3300; } /* Literal.String.Escape */ +.sh { color: #CC3300 } /* Literal.String.Heredoc */ +.si { color: #AA0000 } /* Literal.String.Interpol */ +.sx { color: #CC3300 } /* Literal.String.Other */ +.sr { color: #33AAAA } /* Literal.String.Regex */ +.s1 { color: #CC3300 } /* Literal.String.Single */ +.ss { color: #FFCC33 } /* Literal.String.Symbol */ +.bp { color: #336666 } /* Name.Builtin.Pseudo */ +.vc { color: #003333 } /* Name.Variable.Class */ +.vg { color: #003333 } /* Name.Variable.Global */ +.vi { color: #003333 } /* Name.Variable.Instance */ +.il { color: #FF6600 } /* Literal.Number.Integer.Long */ + +.css .o, +.css .o + .nt, +.css .nt + .nt { color: #999; } diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/flash/ZeroClipboard.swf b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/flash/ZeroClipboard.swf new file mode 100644 index 0000000..55ccf96 Binary files /dev/null and b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/flash/ZeroClipboard.swf differ diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/components.png b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/components.png new file mode 100644 index 0000000..2cbee54 Binary files /dev/null and b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/components.png differ diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/devices.png b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/devices.png new file mode 100644 index 0000000..34c65a0 Binary files /dev/null and b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/devices.png differ diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/sass-less.png b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/sass-less.png new file mode 100644 index 0000000..24cfaf8 Binary files /dev/null and b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/img/sass-less.png differ diff --git a/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/js/customize.min.js b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/js/customize.min.js new file mode 100644 index 0000000..5b641bd --- /dev/null +++ b/src/frontend/static/lib/bootstrap-3.3.5-dist/assets/js/customize.min.js @@ -0,0 +1,91 @@ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.autoprefixer=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gb[0]?1:a[0]0?1:0>c?-1:0)})},e=function(a,b,c){var d,e,f,g,h,i,j,k;c||(g=[b,{}],c=g[0],b=g[1]),e=b.match||/\sx($|\s)/,f=[],h=a.stats;for(d in h){k=h[d];for(j in k)i=k[j],i.match(e)&&f.push(d+" "+j)}return c(l(f))},k={},i=function(){var a,b,c,d,e,f,g,h;for(g=2<=arguments.length?n.call(arguments,0,c=arguments.length-1):(c=0,[]),a=arguments[c++],h=[],d=0,e=g.length;e>d;d++)f=g[d],k[f]={},h.push(function(){var c;c=[];for(b in a)c.push(k[f][b]=a[b]);return c}());return h},c=function(){var a,b,c,d,e,f,g;for(f=2<=arguments.length?n.call(arguments,0,b=arguments.length-1):(b=0,[]),a=arguments[b++],g=[],c=0,d=f.length;d>c;c++)e=f[c],g.push(k[e].browsers=l(k[e].browsers.concat(a.browsers)));return g},b.exports=k,e(a("caniuse-db/features-json/border-radius"),function(a){return i("border-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius",{mistakes:["-ms-","-o-"],transition:!0,browsers:a})}),e(a("caniuse-db/features-json/css-boxshadow"),function(a){return i("box-shadow",{transition:!0,browsers:a})}),e(a("caniuse-db/features-json/css-animation"),function(a){return i("animation","animation-name","animation-duration","animation-delay","animation-direction","animation-fill-mode","animation-iteration-count","animation-play-state","animation-timing-function","@keyframes",{mistakes:["-ms-"],browsers:a})}),e(a("caniuse-db/features-json/css-transitions"),function(a){return i("transition","transition-property","transition-duration","transition-delay","transition-timing-function",{mistakes:["-ms-"],browsers:a})}),e(a("caniuse-db/features-json/transforms2d"),function(a){return i("transform","transform-origin",{transition:!0,browsers:a})}),e(a("caniuse-db/features-json/transforms3d"),function(a){return i("perspective","perspective-origin",{transition:!0,browsers:a}),i("transform-style","backface-visibility",{browsers:a})}),g=a("caniuse-db/features-json/css-gradients"),e(g,{match:/y\sx/},function(a){return i("linear-gradient","repeating-linear-gradient","radial-gradient","repeating-radial-gradient",{props:["background","background-image","border-image","list-style","list-style-image","content","mask-image","mask"],mistakes:["-ms-"],browsers:a})}),e(g,{match:/a\sx/},function(a){return a=a.map(function(a){return/op/.test(a)?a:a+" old"}),c("linear-gradient","repeating-linear-gradient","radial-gradient","repeating-radial-gradient",{browsers:a})}),e(a("caniuse-db/features-json/css3-boxsizing"),function(a){return i("box-sizing",{browsers:a})}),e(a("caniuse-db/features-json/css-filters"),function(a){return i("filter",{transition:!0,browsers:a})}),e(a("caniuse-db/features-json/multicolumn"),function(a){return i("columns","column-width","column-gap","column-rule","column-rule-color","column-rule-width",{transition:!0,browsers:a}),i("column-count","column-rule-style","column-span","column-fill","break-before","break-after","break-inside",{browsers:a})}),e(a("caniuse-db/features-json/user-select-none"),function(a){return i("user-select",{browsers:a})}),f=a("caniuse-db/features-json/flexbox"),e(f,{match:/a\sx/},function(a){return a=a.map(function(a){return/ie|firefox/.test(a)?a:a+" 2009"}),i("display-flex","inline-flex",{props:["display"],browsers:a}),i("flex","flex-grow","flex-shrink","flex-basis",{transition:!0,browsers:a}),i("flex-direction","flex-wrap","flex-flow","justify-content","order","align-items","align-self","align-content",{browsers:a})}),e(f,{match:/y\sx/},function(a){return c("display-flex","inline-flex",{browsers:a}),c("flex","flex-grow","flex-shrink","flex-basis",{browsers:a}),c("flex-direction","flex-wrap","flex-flow","justify-content","order","align-items","align-self","align-content",{browsers:a})}),e(a("caniuse-db/features-json/calc"),function(a){return i("calc",{props:["*"],browsers:a})}),e(a("caniuse-db/features-json/background-img-opts"),function(a){return i("background-clip","background-origin","background-size",{browsers:a})}),e(a("caniuse-db/features-json/font-feature"),function(a){return i("font-feature-settings","font-variant-ligatures","font-language-override","font-kerning",{browsers:a})}),e(a("caniuse-db/features-json/border-image"),function(a){return i("border-image",{browsers:a})}),e(a("caniuse-db/features-json/css-selection"),function(a){return i("::selection",{selector:!0,browsers:a})}),e(a("caniuse-db/features-json/css-placeholder"),function(a){return a=a.map(function(a){var b,c,d;return c=a.split(" "),b=c[0],d=c[1],"firefox"===b&&parseFloat(d)<=18?a+" old":a}),i(":placeholder-shown","::placeholder",{selector:!0,browsers:a})}),e(a("caniuse-db/features-json/css-hyphens"),function(a){return i("hyphens",{browsers:a})}),e(a("caniuse-db/features-json/fullscreen"),function(a){return i(":fullscreen",{selector:!0,browsers:a})}),e(a("caniuse-db/features-json/css3-tabsize"),function(a){return i("tab-size",{browsers:a})}),e(a("caniuse-db/features-json/intrinsic-width"),function(a){return i("max-content","min-content","fit-content","fill-available",{props:["width","min-width","max-width","height","min-height","max-height"],browsers:a})}),e(a("caniuse-db/features-json/css3-cursors-newer"),function(a){return i("zoom-in","zoom-out",{props:["cursor"],browsers:a.concat(["chrome 3"])}),i("grab","grabbing",{props:["cursor"],browsers:a.concat(["firefox 24","firefox 25","firefox 26"])})}),e(a("caniuse-db/features-json/css-sticky"),function(a){return i("sticky",{props:["position"],browsers:a})}),e(a("caniuse-db/features-json/pointer"),function(a){return i("touch-action",{browsers:a})}),m=a("caniuse-db/features-json/text-decoration"),e(m,function(a){return i("text-decoration-style",{browsers:a})}),e(m,{match:/y\sx($|\s)/},function(a){return i("text-decoration-line","text-decoration-color",{browsers:a})}),e(a("caniuse-db/features-json/text-size-adjust"),function(a){return i("text-size-adjust",{browsers:a})}),e(a("caniuse-db/features-json/css-masks"),function(a){return i("mask-clip","mask-composite","mask-image","mask-origin","mask-repeat",{browsers:a}),i("clip-path","mask","mask-position","mask-size",{transition:!0,browsers:a})}),e(a("caniuse-db/features-json/css-boxdecorationbreak"),function(a){return i("box-decoration-break",{browsers:a})}),e(a("caniuse-db/features-json/object-fit"),function(a){return i("object-fit","object-position",{browsers:a})}),e(a("caniuse-db/features-json/css-shapes"),function(a){return i("shape-margin","shape-outside","shape-image-threshold",{browsers:a})}),e(a("caniuse-db/features-json/text-overflow"),function(a){return i("text-overflow",{browsers:a})}),e(a("caniuse-db/features-json/text-emphasis"),function(a){return i("text-emphasis",{browsers:a})}),e(a("caniuse-db/features-json/css-deviceadaptation"),function(a){return i("@viewport",{browsers:a})}),j=a("caniuse-db/features-json/css-media-resolution"),e(j,{match:/( x($| )|a #3)/},function(a){return i("@resolution",{browsers:a})}),e(a("caniuse-db/features-json/css-text-align-last"),function(a){return i("text-align-last",{browsers:a})}),d=a("caniuse-db/features-json/css-crisp-edges"),e(d,{match:/y x/},function(a){return i("crisp-edges",{props:["image-rendering"],browsers:a})}),e(d,{match:/a x #2/},function(a){return i("image-rendering",{browsers:a})}),h=a("caniuse-db/features-json/css-logical-props"),e(h,function(a){return i("border-inline-start","border-inline-end","margin-inline-start","margin-inline-end","padding-inline-start","padding-inline-end",{transition:!0,browsers:a})}),e(h,{match:/x\s#2/},function(a){return i("border-block-start","border-block-end","margin-block-start","margin-block-end","padding-block-start","padding-block-end",{transition:!0,browsers:a})})}).call(this)},{"caniuse-db/features-json/background-img-opts":57,"caniuse-db/features-json/border-image":58,"caniuse-db/features-json/border-radius":59,"caniuse-db/features-json/calc":60,"caniuse-db/features-json/css-animation":61,"caniuse-db/features-json/css-boxdecorationbreak":62,"caniuse-db/features-json/css-boxshadow":63,"caniuse-db/features-json/css-crisp-edges":64,"caniuse-db/features-json/css-deviceadaptation":65,"caniuse-db/features-json/css-filters":66,"caniuse-db/features-json/css-gradients":67,"caniuse-db/features-json/css-hyphens":68,"caniuse-db/features-json/css-logical-props":69,"caniuse-db/features-json/css-masks":70,"caniuse-db/features-json/css-media-resolution":71,"caniuse-db/features-json/css-placeholder":72,"caniuse-db/features-json/css-selection":73,"caniuse-db/features-json/css-shapes":74,"caniuse-db/features-json/css-sticky":75,"caniuse-db/features-json/css-text-align-last":76,"caniuse-db/features-json/css-transitions":77,"caniuse-db/features-json/css3-boxsizing":78,"caniuse-db/features-json/css3-cursors-newer":79,"caniuse-db/features-json/css3-tabsize":80,"caniuse-db/features-json/flexbox":81,"caniuse-db/features-json/font-feature":82,"caniuse-db/features-json/fullscreen":83,"caniuse-db/features-json/intrinsic-width":84,"caniuse-db/features-json/multicolumn":85,"caniuse-db/features-json/object-fit":86,"caniuse-db/features-json/pointer":87,"caniuse-db/features-json/text-decoration":88,"caniuse-db/features-json/text-emphasis":89,"caniuse-db/features-json/text-overflow":90,"caniuse-db/features-json/text-size-adjust":91,"caniuse-db/features-json/transforms2d":92,"caniuse-db/features-json/transforms3d":93,"caniuse-db/features-json/user-select-none":94}],3:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("./prefixer"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.prototype.add=function(a,b){var c,d,e;return e=b+a.name,(c=a.parent.some(function(b){return b.name===e&&b.params===a.params}))?void 0:(d=this.clone(a,{name:e}),a.parent.insertBefore(a,d))},b.prototype.process=function(a){var b,c,d,e,f,g;for(d=this.parentPrefix(a),f=this.prefixes,g=[],b=0,c=f.length;c>b;b++)e=f[b],d&&d!==e||g.push(this.add(a,e));return g},b}(d),b.exports=c}).call(this)},{"./prefixer":40}],4:[function(a,b,c){(function(){var c,d,e;d=a("browserslist"),e=a("./utils"),c=function(){function b(a,b,c){this.data=a,this.options=c,this.selected=this.parse(b)}return b.prefixes=function(){var b,c,d;return this.prefixesCache?this.prefixesCache:(b=a("caniuse-db/data").agents,this.prefixesCache=e.uniq(function(){var a;a=[];for(d in b)c=b[d],a.push("-"+c.prefix+"-");return a}()).sort(function(a,b){return b.length-a.length}))},b.withPrefix=function(a){return this.prefixesRegexp||(this.prefixesRegexp=RegExp(""+this.prefixes().join("|"))),this.prefixesRegexp.test(a)},b.prototype.parse=function(a){var b;return d(a,{path:null!=(b=this.options)?b.from:void 0})},b.prototype.browsers=function(a){var b,c,d,e,f;e=[],d=this.data;for(b in d)c=d[b],f=a(c).map(function(a){return b+" "+a}),e=e.concat(f);return e},b.prototype.prefix=function(a){var b,c,d,e,f;return e=a.split(" "),c=e[0],f=e[1],b=this.data[c],b.prefix_exceptions&&(d=b.prefix_exceptions[f]),d||(d=b.prefix),"-"+d+"-"},b.prototype.isSelected=function(a){return-1!==this.selected.indexOf(a)},b}(),b.exports=c}).call(this)},{"./utils":46,browserslist:55,"caniuse-db/data":56}],5:[function(a,b,c){(function(){var c,d,e,f,g,h=function(a,b){function c(){this.constructor=a}for(var d in b)i.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i={}.hasOwnProperty;e=a("./prefixer"),c=a("./browsers"),g=a("postcss/lib/vendor"),f=a("./utils"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return h(b,a),b.prototype.check=function(a){return!0},b.prototype.prefixed=function(a,b){return b+a},b.prototype.normalize=function(a){return a},b.prototype.otherPrefixes=function(a,b){var d,e,f,g;for(g=c.prefixes(),d=0,e=g.length;e>d;d++)if(f=g[d],f!==b&&-1!==a.indexOf(f))return!0;return!1},b.prototype.set=function(a,b){return a.prop=this.prefixed(a.prop,b),a},b.prototype.needCascade=function(a){return a._autoprefixerCascade||(a._autoprefixerCascade=this.all.options.cascade!==!1&&-1!==a.style("before").indexOf("\n"))},b.prototype.maxPrefixed=function(a,b){var c,d,e,g;if(b._autoprefixerMax)return b._autoprefixerMax;for(e=0,c=0,d=a.length;d>c;c++)g=a[c],g=f.removeNote(g),g.length>e&&(e=g.length);return b._autoprefixerMax=e},b.prototype.calcBefore=function(a,b,c){var d,e,g,h,i,j;for(null==c&&(c=""),d=b.style("before"),i=this.maxPrefixed(a,b),e=i-f.removeNote(c).length,g=h=0,j=e;j>=0?j>h:h>j;g=j>=0?++h:--h)d+=" ";return d},b.prototype.restoreBefore=function(a){var b,c;return b=a.style("before").split("\n"),c=b[b.length-1],this.all.group(a).up(function(a){var b,d;return b=a.style("before").split("\n"),d=b[b.length-1],d.lengthd;d++)for(m=k[d],l=["left","right"],f=0,h=l.length;h>f;f++)c=l[f],j="border-"+m+"-"+c+"-radius",i="border-radius-"+m+c,b.names.push(j),b.names.push(i),b.toMozilla[j]=i,b.toNormal[i]=j;return b.prototype.prefixed=function(a,c){return"-moz-"===c?c+(b.toMozilla[a]||a):b.__super__.prefixed.apply(this,arguments)},b.prototype.normalize=function(a){return b.toNormal[a]||a},b}(d),b.exports=c}).call(this)},{"../declaration":5}],13:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("../declaration"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["break-inside","page-break-inside","column-break-inside"],b.prototype.prefixed=function(a,c){return"-webkit-"===c?c+"column-break-inside":"-moz-"===c?"page-break-inside":b.__super__.prefixed.apply(this,arguments)},b.prototype.normalize=function(){return"break-inside"},b.prototype.set=function(a,c){return("avoid-column"===a.value||"avoid-page"===a.value)&&(a.value="avoid"),b.__super__.set.apply(this,arguments)},b.prototype.insert=function(a,c,d){if("avoid-region"===a.value);else if("avoid-page"!==a.value||"-webkit-"!==c)return b.__super__.insert.apply(this,arguments)},b}(d),b.exports=c}).call(this)},{"../declaration":5}],14:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("../value"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["crisp-edges"],b.prototype.replace=function(a,c){return"-webkit-"===c?a.replace(this.regexp(),"$1-webkit-optimize-contrast"):b.__super__.replace.apply(this,arguments)},b}(d),b.exports=c}).call(this)},{"../value":47}],15:[function(a,b,c){(function(){var c,d,e,f,g,h=function(a,b){function c(){this.constructor=a}for(var d in b)i.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i={}.hasOwnProperty;g=a("./flex-spec"),e=a("../old-value"),f=a("../value"),d=function(a){function b(a,b){this.unprefixed=a,this.prefixed=b}return h(b,a),b.prototype.check=function(a){return a===this.name},b}(e),c=function(a){function b(a,c){b.__super__.constructor.apply(this,arguments),"display-flex"===a&&(this.name="flex")}return h(b,a),b.names=["display-flex","inline-flex"],b.prototype.check=function(a){return a.value===this.name},b.prototype.prefixed=function(a){var b,c;return b=g(a),c=b[0],a=b[1],a+(2009===c?"flex"===this.name?"box":"inline-box":2012===c?"flex"===this.name?"flexbox":"inline-flexbox":"final"===c?this.name:void 0)},b.prototype.replace=function(a,b){return this.prefixed(b)},b.prototype.old=function(a){var b;return b=this.prefixed(a),b?new e(this.name,b):void 0},b}(f),b.exports=c}).call(this)},{"../old-value":39,"../value":47,"./flex-spec":24}],16:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;d=a("../old-value"),e=a("../value"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["fill-available"],b.prototype.replace=function(a,c){return"-moz-"===c?a.replace(this.regexp(),"$1-moz-available$3"):b.__super__.replace.apply(this,arguments)},b.prototype.old=function(a){return"-moz-"===a?new d(this.name,"-moz-available"):b.__super__.old.apply(this,arguments)},b}(e),b.exports=c}).call(this)},{"../old-value":39,"../value":47}],17:[function(a,b,c){(function(){var c,d,e,f,g,h=function(a,b){function c(){this.constructor=a}for(var d in b)i.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i={}.hasOwnProperty;e=a("../old-value"),f=a("../value"),g=a("../utils"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return h(b,a),b.prototype.clean=function(a){return a.value=g.editList(a.value,function(a){return function(b){return b.every(function(b){return 0!==b.indexOf(a.unprefixed)})?b:b.filter(function(b){return-1===b.indexOf(a.prefixed)})}}(this))},b}(e),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return h(b,a),b.names=["filter"],b.prototype.replace=function(a,c){return"-webkit-"===c?-1===a.indexOf("-webkit-filter")?b.__super__.replace.apply(this,arguments)+", "+a:a:b.__super__.replace.apply(this,arguments)},b.prototype.old=function(a){return new d(this.name,a+this.name)},b}(f),b.exports=c}).call(this)},{"../old-value":39,"../utils":46,"../value":47}],18:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["filter"],b.prototype.check=function(a){var b;return b=a.value,-1===b.toLowerCase().indexOf("alpha(")&&-1===b.indexOf("DXImageTransform.Microsoft")&&-1===b.indexOf("data:image/svg+xml")},b}(c),b.exports=d}).call(this)},{"../declaration":5}],19:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-basis","flex-preferred-size"],b.prototype.normalize=function(){return"flex-basis"},b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2012===f?c+"flex-preferred-size":b.__super__.prefixed.apply(this,arguments)},b.prototype.set=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2012===f||"final"===f?b.__super__.set.apply(this,arguments):void 0},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],20:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-direction","box-direction","box-orient"],b.prototype.normalize=function(a){return"flex-direction"},b.prototype.insert=function(a,c,d){var f,g,h,i,j,k,l;if(j=e(c),k=j[0],c=j[1],2009===k){if(f=a.parent.some(function(a){return a.prop===c+"box-orient"||a.prop===c+"box-direction"}))return;return l=a.value,i=-1!==l.indexOf("row")?"horizontal":"vertical",h=-1!==l.indexOf("reverse")?"reverse":"normal",g=this.clone(a),g.prop=c+"box-orient",g.value=i,this.needCascade(a)&&(g.before=this.calcBefore(d,a,c)),a.parent.insertBefore(a,g),g=this.clone(a),g.prop=c+"box-direction",g.value=h,this.needCascade(a)&&(g.before=this.calcBefore(d,a,c)),a.parent.insertBefore(a,g)}return b.__super__.insert.apply(this,arguments)},b.prototype.old=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2009===f?[c+"box-orient",c+"box-direction"]:b.__super__.old.apply(this,arguments)},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],21:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-flow"],b.prototype.set=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2012===f?b.__super__.set.apply(this,arguments):"final"===f?b.__super__.set.apply(this,arguments):void 0},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],22:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-grow","flex-positive"],b.prototype.normalize=function(){return"flex"},b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2009===f?c+"box-flex":2012===f?c+"flex-positive":b.__super__.prefixed.apply(this,arguments)},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],23:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-shrink","flex-negative"],b.prototype.normalize=function(){return"flex-shrink"},b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2012===f?c+"flex-negative":b.__super__.prefixed.apply(this,arguments)},b.prototype.set=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2012===f||"final"===f?b.__super__.set.apply(this,arguments):void 0},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],24:[function(a,b,c){(function(){b.exports=function(a){var b;return b="-webkit- 2009"===a||"-moz-"===a?2009:"-ms-"===a?2012:"-webkit-"===a?"final":void 0,"-webkit- 2009"===a&&(a="-webkit-"),[b,a]}}).call(this)},{}],25:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;d=a("../old-value"),e=a("../value"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex","flex-grow","flex-shrink","flex-basis"],b.prototype.prefixed=function(a){return this.all.prefixed(this.name,a)},b.prototype.replace=function(a,b){return a.replace(this.regexp(),"$1"+this.prefixed(b)+"$3")},b.prototype.old=function(a){ +return new d(this.name,this.prefixed(a))},b}(e),b.exports=c}).call(this)},{"../old-value":39,"../value":47}],26:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["flex-wrap"],b.prototype.set=function(a,c){var d;return d=e(c)[0],2009!==d?b.__super__.set.apply(this,arguments):void 0},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],27:[function(a,b,c){(function(){var c,d,e,f,g=function(a,b){function c(){this.constructor=a}for(var d in b)h.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},h={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),f=a("postcss/lib/list"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return g(b,a),b.names=["flex","box-flex"],b.oldValues={auto:"1",none:"0"},b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2009===f?c+"box-flex":b.__super__.prefixed.apply(this,arguments)},b.prototype.normalize=function(){return"flex"},b.prototype.set=function(a,c){var d;return d=e(c)[0],2009===d?(a.value=f.space(a.value)[0],a.value=b.oldValues[a.value]||a.value,b.__super__.set.call(this,a,c)):b.__super__.set.apply(this,arguments)},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24,"postcss/lib/list":102}],28:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("../selector"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=[":fullscreen"],b.prototype.prefixed=function(a){return"-webkit-"===a?":-webkit-full-screen":"-moz-"===a?":-moz-full-screen":":"+a+"fullscreen"},b}(d),b.exports=c}).call(this)},{"../selector":44}],29:[function(a,b,c){(function(){var c,d,e,f,g,h,i=function(a,b){function c(){this.constructor=a}for(var d in b)j.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},j={}.hasOwnProperty;d=a("../old-value"),e=a("../value"),h=a("../utils"),g=a("postcss/lib/list"),f=/top|left|right|bottom/gi,c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return i(b,a),b.names=["linear-gradient","repeating-linear-gradient","radial-gradient","repeating-radial-gradient"],b.prototype.replace=function(a,b){return g.space(a).map(function(a){return function(c){var d,e,f,h;return c.slice(0,+a.name.length+1||9e9)!==a.name+"("?c:(f=c.lastIndexOf(")"),d=c.slice(f+1),e=c.slice(a.name.length+1,+(f-1)+1||9e9),h=g.comma(e),h=a.newDirection(h),"-webkit- old"===b?a.oldWebkit(c,e,h,d):(a.convertDirection(h),b+a.name+"("+h.join(", ")+")"+d))}}(this)).join(" ")},b.prototype.directions={top:"bottom",left:"right",bottom:"top",right:"left"},b.prototype.oldDirections={top:"left bottom, left top",left:"right top, left top",bottom:"left top, left bottom",right:"left top, right top","top right":"left bottom, right top","top left":"right bottom, left top","right top":"left bottom, right top","right bottom":"left top, right bottom","bottom right":"left top, right bottom","bottom left":"right top, left bottom","left top":"right bottom, left top","left bottom":"right top, left bottom"},b.prototype.newDirection=function(a){var b,c;return b=a[0],-1===b.indexOf("to ")&&f.test(b)&&(b=b.split(" "),b=function(){var a,d,e;for(e=[],a=0,d=b.length;d>a;a++)c=b[a],e.push(this.directions[c.toLowerCase()]||c);return e}.call(this),a[0]="to "+b.join(" ")),a},b.prototype.oldWebkit=function(a,b,c,d){return-1!==b.indexOf("px")?a:"linear-gradient"!==this.name?a:c[0]&&-1!==c[0].indexOf("deg")?a:-1!==b.indexOf("-corner")?a:-1!==b.indexOf("-side")?a:(c=this.oldDirection(c),c=this.colorStops(c),"-webkit-gradient(linear, "+c.join(", ")+")"+d)},b.prototype.convertDirection=function(a){if(a.length>0){if("to "===a[0].slice(0,3))return a[0]=this.fixDirection(a[0]);if(-1!==a[0].indexOf("deg"))return a[0]=this.fixAngle(a[0]);if(-1!==a[0].indexOf(" at "))return this.fixRadial(a)}},b.prototype.fixDirection=function(a){var b;return a=a.split(" "),a.splice(0,1),a=function(){var c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(this.directions[b.toLowerCase()]||b);return e}.call(this),a.join(" ")},b.prototype.roundFloat=function(a,b){return parseFloat(a.toFixed(b))},b.prototype.fixAngle=function(a){return a=parseFloat(a),a=Math.abs(450-a)%360,a=this.roundFloat(a,3),a+"deg"},b.prototype.oldDirection=function(a){var b;return 0===a.length,-1!==a[0].indexOf("to ")?(b=a[0].replace(/^to\s+/,""),b=this.oldDirections[b],a[0]=b,a):(b=this.oldDirections.bottom,[b].concat(a))},b.prototype.colorStops=function(a){return a.map(function(b,c){var d,e,f,h;return 0===c?b:(h=g.space(b),d=h[0],f=h[1],null==f&&(e=b.match(/^(.*\))(\d.*)$/),e&&(d=e[1],f=e[2])),f&&-1!==f.indexOf(")")&&(d+=" "+f,f=void 0),1!==c||void 0!==f&&"0%"!==f?c!==a.length-1||void 0!==f&&"100%"!==f?f?"color-stop("+f+", "+d+")":"color-stop("+d+")":"to("+d+")":"from("+d+")")})},b.prototype.fixRadial=function(a){var b;return b=a[0].split(/\s+at\s+/),a.splice(0,1,b[1],b[0])},b.prototype.old=function(a){var c,e,f;return"-webkit-"===a?(f="linear-gradient"===this.name?"linear":"radial",e="-gradient",c=h.regexp("-webkit-("+f+"-gradient|gradient\\(\\s*"+f+")",!1),new d(this.name,a+this.name,e,c)):b.__super__.old.apply(this,arguments)},b.prototype.add=function(a,c){var d;if(d=a.prop,-1!==d.indexOf("mask")){if("-webkit-"===c||"-webkit- old"===c)return b.__super__.add.apply(this,arguments)}else{if("list-style"!==d&&"list-style-image"!==d&&"content"!==d)return b.__super__.add.apply(this,arguments);if("-webkit-"===c||"-webkit- old"===c)return b.__super__.add.apply(this,arguments)}},b}(e),b.exports=c}).call(this)},{"../old-value":39,"../utils":46,"../value":47,"postcss/lib/list":102}],30:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["image-rendering","interpolation-mode"],b.prototype.check=function(a){return"crisp-edges"===a.value},b.prototype.prefixed=function(a,c){return"-ms-"===c?"-ms-interpolation-mode":b.__super__.prefixed.apply(this,arguments)},b.prototype.set=function(a,c){return"-ms-"===c?(a.prop="-ms-interpolation-mode",a.value="nearest-neighbor",a):b.__super__.set.apply(this,arguments)},b.prototype.normalize=function(a){return"image-rendering"},b}(c),b.exports=d}).call(this)},{"../declaration":5}],31:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["border-inline-start","border-inline-end","margin-inline-start","margin-inline-end","padding-inline-start","padding-inline-end","border-start","border-end","margin-start","margin-end","padding-start","padding-end"],b.prototype.prefixed=function(a,b){return b+a.replace("-inline","")},b.prototype.normalize=function(a){return a.replace(/(margin|padding|border)-(start|end)/,"$1-inline-$2")},b}(c),b.exports=d}).call(this)},{"../declaration":5}],32:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["justify-content","flex-pack","box-pack"],b.oldValues={"flex-end":"end","flex-start":"start","space-between":"justify","space-around":"distribute"},b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2009===f?c+"box-pack":2012===f?c+"flex-pack":b.__super__.prefixed.apply(this,arguments)},b.prototype.normalize=function(a){return"justify-content"},b.prototype.set=function(a,c){var d,f;if(d=e(c)[0],2009===d||2012===d){if(f=b.oldValues[a.value]||a.value,a.value=f,2009!==d||"distribute"!==f)return b.__super__.set.call(this,a,c)}else if("final"===d)return b.__super__.set.apply(this,arguments)},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],33:[function(a,b,c){(function(){var c,d,e,f=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},g={}.hasOwnProperty;e=a("./flex-spec"),c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return f(b,a),b.names=["order","flex-order","box-ordinal-group"],b.prototype.prefixed=function(a,c){var d,f;return d=e(c),f=d[0],c=d[1],2009===f?c+"box-ordinal-group":2012===f?c+"flex-order":b.__super__.prefixed.apply(this,arguments)},b.prototype.normalize=function(a){return"order"},b.prototype.set=function(a,c){var d;return d=e(c)[0],2009===d?(a.value=(parseInt(a.value)+1).toString(),b.__super__.set.call(this,a,c)):b.__super__.set.apply(this,arguments)},b}(c),b.exports=d}).call(this)},{"../declaration":5,"./flex-spec":24}],34:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("../selector"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=[":placeholder-shown","::placeholder"],b.prototype.possible=function(){return b.__super__.possible.apply(this,arguments).concat("-moz- old")},b.prototype.prefixed=function(a){return"-webkit-"===a?"::-webkit-input-placeholder":"-ms-"===a?":-ms-input-placeholder":"-moz- old"===a?":-moz-placeholder":"::"+a+"placeholder"},b}(d),b.exports=c}).call(this)},{"../selector":44}],35:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;c=a("../declaration"),d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["transform","transform-origin"],b.functions3d=["matrix3d","translate3d","translateZ","scale3d","scaleZ","rotate3d","rotateX","rotateY","rotateZ","perspective"],b.prototype.keykrameParents=function(a){var b;for(b=a.parent;b;){if("atrule"===b.type&&"keyframes"===b.name)return!0;b=b.parent}return!1},b.prototype.contain3d=function(a){var c,d,e,f;if("transform-origin"===a.prop)return!1;for(f=b.functions3d,d=0,e=f.length;e>d;d++)if(c=f[d],-1!==a.value.indexOf(c+"("))return!0;return!1},b.prototype.insert=function(a,c,d){if("-ms-"===c){if(!this.contain3d(a)&&!this.keykrameParents(a))return b.__super__.insert.apply(this,arguments)}else{if("-o-"!==c)return b.__super__.insert.apply(this,arguments);if(!this.contain3d(a))return b.__super__.insert.apply(this,arguments)}},b}(c),b.exports=d}).call(this)},{"../declaration":5}],36:[function(a,b,c){(function(){var c,d,e=function(a,b){function c(){this.constructor=a}for(var d in b)f.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},f={}.hasOwnProperty;d=a("../value"),c=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return e(b,a),b.names=["transform"],b.prototype.replace=function(a,c){return"-ms-"===c?a:b.__super__.replace.apply(this,arguments)},b}(d),b.exports=c}).call(this)},{"../value":47}],37:[function(a,b,c){(function(){var a,c,d;a=function(a){return a.slice(0,1).toUpperCase()+a.slice(1)},c={ie:"IE",ie_mob:"IE Mobile",ios_saf:"iOS",op_mini:"Opera Mini",op_mob:"Opera Mobile",and_chr:"Chrome for Android",and_ff:"Firefox for Android",and_uc:"UC for Android"},d=function(a,b,c){var d;return d=" "+a+(b?"*":"")+": ",d+=c.map(function(a){return a.replace(/^-(.*)-$/g,"$1")}).join(", "),d+="\n"},b.exports=function(b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H;if(0===b.browsers.selected.length)return"No browsers selected";for(H=[],s=b.browsers.selected,h=0,k=s.length;k>h;h++)f=s[h],t=f.split(" "),o=t[0],G=t[1],o=c[o]||a(o),H[o]?H[o].push(G):H[o]=[G];q="Browsers:\n";for(f in H)n=H[f],n=n.sort(function(a,b){return parseFloat(b)-parseFloat(a)}),q+=" "+f+": "+n.join(", ")+"\n";e="",u=b.add;for(o in u)g=u[o],"@"===o[0]&&g.prefixes&&(e+=d(o,!1,g.prefixes));for(""!==e&&(q+="\nAt-Rules:\n"+e),A="",v=b.add.selectors,i=0,l=v.length;l>i;i++)z=v[i],z.prefixes&&(A+=d(z.name,!1,z.prefixes));""!==A&&(q+="\nSelectors:\n"+A),F="",r="",D=!1,p=null!=(w=b.add.transition)?w.prefixes:void 0,x=b.add;for(o in x)if(g=x[o],"@"!==o[0]&&g.prefixes&&(C=p&&b.data[o].transition,C&&(D=!0),r+=d(o,C,g.prefixes)),g.values&&!b.transitionProps.some(function(a){return a===o}))for(y=g.values,j=0,m=y.length;m>j;j++)E=y[j],B=d(E.name,!1,E.prefixes),-1===F.indexOf(B)&&(F+=B);return D&&(r+=" * - can be used in transition\n"),""!==r&&(q+="\nProperties:\n"+r),""!==F&&(q+="\nValues:\n"+F),""===e&&""===A&&""===r&&""===F&&(q+="\nAwesome! Your browsers don't require any vendor prefixes.\nNow you can remove Autoprefixer from build steps."),q}}).call(this)},{}],38:[function(a,b,c){(function(){var a;a=function(){function a(a,b){var c,d,e,f;for(this.prefix=b,this.prefixed=a.prefixed(this.prefix),this.regexp=a.regexp(this.prefix),this.prefixeds=[],f=a.possible(),c=0,d=f.length;d>c;c++)e=f[c],this.prefixeds.push([a.prefixed(e),a.regexp(e)]);this.unprefixed=a.name,this.nameRegexp=a.regexp()}return a.prototype.isHack=function(a){var b,c,d,e,f,g,h,i,j,k;for(d=a.parent.index(a)+1,i=a.parent.nodes;dc;c++)if(g=f[c],k=g[0],h=g[1],-1!==b.indexOf(k)&&b.match(h)){j=!0;break}if(!j)return!0;d+=1}return!0},a.prototype.check=function(a){return-1===a.selector.indexOf(this.prefixed)?!1:a.selector.match(this.regexp)?this.isHack(a)?!1:!0:!1},a}(),b.exports=a}).call(this)},{}],39:[function(a,b,c){(function(){var c,d;d=a("./utils"),c=function(){function a(a,b,c,e){this.unprefixed=a,this.prefixed=b,this.string=c,this.regexp=e,this.regexp||(this.regexp=d.regexp(this.prefixed)),this.string||(this.string=this.prefixed)}return a.prototype.check=function(a){return-1!==a.indexOf(this.string)?!!a.match(this.regexp):!1},a}(),b.exports=c}).call(this)},{"./utils":46}],40:[function(a,b,c){(function(){var c,d,e,f,g,h={}.hasOwnProperty;c=a("./browsers"),f=a("./utils"),g=a("postcss/lib/vendor"),e=function(a,b){var c,d,f;if("object"!=typeof a)return a;c=new a.constructor;for(d in a)h.call(a,d)&&(f=a[d],"parent"===d&&"object"==typeof f?b&&(c[d]=b):"source"===d?c[d]=f:f instanceof Array?c[d]=f.map(function(a){return e(a,c)}):"_autoprefixerPrefix"!==d&&"_autoprefixerValues"!==d&&(c[d]=e(f,c)));return c},d=function(){function a(a,b,c){this.name=a,this.prefixes=b,this.all=c}return a.hack=function(a){var b,c,d,e,f;for(this.hacks||(this.hacks={}),e=a.names,f=[],b=0,c=e.length;c>b;b++)d=e[b],f.push(this.hacks[d]=a);return f},a.load=function(a,b,c){var d,e;return d=null!=(e=this.hacks)?e[a]:void 0,d?new d(a,b,c):new this(a,b,c)},a.clone=function(a,b){var c,d;c=e(a);for(d in b)c[d]=b[d];return c},a.prototype.parentPrefix=function(a){var b;return b=null!=a._autoprefixerPrefix?a._autoprefixerPrefix:"decl"===a.type&&"-"===a.prop[0]?g.prefix(a.prop):"root"===a.type?!1:"rule"===a.type&&-1!==a.selector.indexOf(":-")?a.selector.match(/:(-\w+-)/)[1]:"atrule"===a.type&&"-"===a.name[0]?g.prefix(a.name):this.parentPrefix(a.parent),-1===c.prefixes().indexOf(b)&&(b=!1),a._autoprefixerPrefix=b},a.prototype.process=function(a){var b,c,d,e,g,h,i,j,k;if(this.check(a)){for(h=this.parentPrefix(a),j=[],k=this.prefixes,c=0,e=k.length;e>c;c++)i=k[c],h&&h!==f.removeNote(i)||j.push(i);for(b=[],d=0,g=j.length;g>d;d++)i=j[d],this.add(a,i,b.concat([i]))&&b.push(i);return b}},a.prototype.clone=function(b,c){return a.clone(b,c)},a}(),b.exports=d}).call(this)},{"./browsers":4,"./utils":46,"postcss/lib/vendor":113}],41:[function(a,b,c){(function(){var c,d,e,f,g,h,i,j,k,l,m,n;e=a("./declaration"),h=a("./resolution"),g=a("./processor"),j=a("./supports"),d=a("./browsers"),i=a("./selector"),c=a("./at-rule"),k=a("./value"),m=a("./utils"),n=a("postcss/lib/vendor"),i.hack(a("./hacks/fullscreen")),i.hack(a("./hacks/placeholder")),e.hack(a("./hacks/flex")),e.hack(a("./hacks/order")),e.hack(a("./hacks/filter")),e.hack(a("./hacks/flex-flow")),e.hack(a("./hacks/flex-grow")),e.hack(a("./hacks/flex-wrap")),e.hack(a("./hacks/align-self")),e.hack(a("./hacks/flex-basis")),e.hack(a("./hacks/align-items")),e.hack(a("./hacks/flex-shrink")),e.hack(a("./hacks/break-inside")),e.hack(a("./hacks/border-image")),e.hack(a("./hacks/align-content")),e.hack(a("./hacks/border-radius")),e.hack(a("./hacks/block-logical")),e.hack(a("./hacks/inline-logical")),e.hack(a("./hacks/transform-decl")),e.hack(a("./hacks/flex-direction")),e.hack(a("./hacks/image-rendering")),e.hack(a("./hacks/justify-content")),e.hack(a("./hacks/background-size")),k.hack(a("./hacks/gradient")),k.hack(a("./hacks/crisp-edges")),k.hack(a("./hacks/flex-values")),k.hack(a("./hacks/display-flex")),k.hack(a("./hacks/filter-value")),k.hack(a("./hacks/fill-available")),k.hack(a("./hacks/transform-value")),l={},f=function(){function a(a,b,c){var d;this.data=a,this.browsers=b,this.options=null!=c?c:{},d=this.preprocess(this.select(this.data)),this.add=d[0],this.remove=d[1],this.processor=new g(this)}return a.prototype.transitionProps=["transition","transition-property"],a.prototype.cleaner=function(){var b;if(!this.cleanerCache){if(!this.browsers.selected.length)return this;b=new d(this.browsers.data,[]),this.cleanerCache=new a(this.data,b,this.options)}return this.cleanerCache},a.prototype.select=function(a){var b,c,d,e,f,g;g={add:{},remove:{}};for(e in a)d=a[e],b=d.browsers.map(function(a){var b;return b=a.split(" "),{browser:b[0]+" "+b[1],note:b[2]}}),f=b.filter(function(a){return a.note}).map(function(a){return function(b){return a.browsers.prefix(b.browser)+" "+b.note}}(this)),f=m.uniq(f),b=b.filter(function(a){return function(b){return a.browsers.isSelected(b.browser)}}(this)).map(function(a){return function(b){var c;return c=a.browsers.prefix(b.browser),b.note?c+" "+b.note:c}}(this)),b=this.sort(m.uniq(b)),c=d.browsers.map(function(a){return function(b){return a.browsers.prefix(b)}}(this)),d.mistakes&&(c=c.concat(d.mistakes)),c=c.concat(f),c=m.uniq(c),b.length?(g.add[e]=b,b.lengthd;d++)D=E[d],b[D]||(b[D]={values:[]}),b[D].values.push(K);this.data[v].props||(L=(null!=(G=b[v])?G.values:void 0)||[],b[v]=e.load(v,C,this),b[v].values=L)}I={selectors:[]},H=a.remove;for(v in H)if(C=H[v],this.data[v].selector)for(J=i.load(v,C),f=0,m=C.length;m>f;f++)A=C[f],I.selectors.push(J.old(A));else if("@keyframes"===v||"@viewport"===v)for(g=0,o=C.length;o>g;g++)A=C[g],B="@"+A+v.slice(1),I[B]={remove:!0};else if("@resolution"===v)I[v]=new h(v,C,this);else{if(E=this.data[v].transition?this.transitionProps:this.data[v].props)for(K=k.load(v,[],this),t=0,p=C.length;p>t;t++)if(A=C[t],x=K.old(A))for(u=0,q=E.length;q>u;u++)D=E[u],I[D]||(I[D]={}),I[D].values||(I[D].values=[]),I[D].values.push(x);if(!this.data[v].props)for(w=0,r=C.length;r>w;w++)for(A=C[w],D=n.unprefixed(v),y=this.decl(v).old(v,A),z=0,s=y.length;s>z;z++)B=y[z],I[B]||(I[B]={}),I[B].remove=!0}return[b,I]},a.prototype.decl=function(a){var b;return b=l[a],b?b:l[a]=e.load(a)},a.prototype.unprefixed=function(a){return a=n.unprefixed(a),this.decl(a).normalize(a)},a.prototype.prefixed=function(a,b){return a=n.unprefixed(a),this.decl(a).prefixed(a,b)},a.prototype.values=function(a,b){var c,d,e,f,g;return c=this[a],d=null!=(e=c["*"])?e.values:void 0,g=null!=(f=c[b])?f.values:void 0,d&&g?m.uniq(d.concat(g)):d||g||[]},a.prototype.group=function(a){var b,c,e,f,g;return f=a.parent,c=f.index(a),e=f.nodes.length,g=this.unprefixed(a.prop),b=function(a){return function(b,h){var i;for(c+=b;c>=0&&e>c;){if(i=f.nodes[c],"decl"===i.type){if(-1===b&&i.prop===g&&!d.withPrefix(i.value))break;if(a.unprefixed(i.prop)!==g)break;if(h(i)===!0)return!0;if(1===b&&i.prop===g&&!d.withPrefix(i.value))break}c+=b}return!1}}(this),{up:function(a){return b(-1,a)},down:function(a){return b(1,a)}}},a}(),b.exports=f}).call(this)},{"./at-rule":3,"./browsers":4,"./declaration":5,"./hacks/align-content":6,"./hacks/align-items":7,"./hacks/align-self":8,"./hacks/background-size":9,"./hacks/block-logical":10,"./hacks/border-image":11,"./hacks/border-radius":12,"./hacks/break-inside":13,"./hacks/crisp-edges":14,"./hacks/display-flex":15,"./hacks/fill-available":16,"./hacks/filter":18,"./hacks/filter-value":17,"./hacks/flex":27,"./hacks/flex-basis":19,"./hacks/flex-direction":20,"./hacks/flex-flow":21,"./hacks/flex-grow":22,"./hacks/flex-shrink":23,"./hacks/flex-values":25,"./hacks/flex-wrap":26,"./hacks/fullscreen":28,"./hacks/gradient":29,"./hacks/image-rendering":30,"./hacks/inline-logical":31,"./hacks/justify-content":32,"./hacks/order":33,"./hacks/placeholder":34,"./hacks/transform-decl":35,"./hacks/transform-value":36,"./processor":42,"./resolution":43,"./selector":44,"./supports":45,"./utils":46,"./value":47,"postcss/lib/vendor":113}],42:[function(a,b,c){(function(){var c,d,e,f;f=a("postcss/lib/vendor"),d=a("./value"),e=a("./utils"),c=function(){function a(a){this.prefixes=a}return a.prototype.add=function(a){var b,c,e,f;return c=this.prefixes.add["@resolution"],b=this.prefixes.add["@keyframes"],f=this.prefixes.add["@viewport"],e=this.prefixes.add["@supports"],a.eachAtRule(function(a){return function(d){if("keyframes"===d.name){if(!a.disabled(d))return null!=b?b.process(d):void 0}else if("viewport"===d.name){if(!a.disabled(d))return null!=f?f.process(d):void 0}else if("supports"===d.name){if(!a.disabled(d))return e.process(d)}else if("media"===d.name&&-1!==d.params.indexOf("-resolution")&&!a.disabled(d))return null!=c?c.process(d):void 0}}(this)),a.eachRule(function(a){return function(b){var c,d,e,f,g;if(!a.disabled(b)){for(e=a.prefixes.add.selectors,f=[],c=0,d=e.length;d>c;c++)g=e[c],f.push(g.process(b));return f}}}(this)),a.eachDecl(function(a){return function(b){var c;return c=a.prefixes.add[b.prop],c&&c.prefixes&&!a.disabled(b)?c.process(b):void 0}}(this)),a.eachDecl(function(a){return function(b){var c,e,f,g,h;if(!a.disabled(b)){for(g=a.prefixes.unprefixed(b.prop),f=a.prefixes.values("add",g),c=0,e=f.length;e>c;c++)h=f[c],h.process(b);return d.save(a.prefixes,b)}}}(this))},a.prototype.remove=function(a){var b,c,d,e,f;for(f=this.prefixes.remove["@resolution"],a.eachAtRule(function(a){return function(b,c){if(a.prefixes.remove["@"+b.name]){if(!a.disabled(b))return b.parent.remove(c)}else if("media"===b.name&&-1!==b.params.indexOf("-resolution"))return null!=f?f.clean(b):void 0}}(this)),e=this.prefixes.remove.selectors,c=0,d=e.length;d>c;c++)b=e[c],a.eachRule(function(a){return function(c,d){return b.check(c)&&!a.disabled(c)?c.parent.remove(d):void 0}}(this));return a.eachDecl(function(a){return function(c,d){var e,f,g,h,i,j,k;if(!a.disabled(c)){if(j=c.parent,k=a.prefixes.unprefixed(c.prop),(null!=(h=a.prefixes.remove[c.prop])?h.remove:void 0)&&(g=a.prefixes.group(c).down(function(a){return a.prop===k}),g&&!a.withHackValue(c)))return c.style("before").indexOf("\n")>-1&&a.reduceSpaces(c),void j.remove(d);for(i=a.prefixes.values("remove",k),e=0,f=i.length;f>e;e++)if(b=i[e],b.check(c.value)){if(k=b.unprefixed,g=a.prefixes.group(c).down(function(a){return-1!==a.value.indexOf(k)}))return void j.remove(d);if(b.clean)return void b.clean(c)}}}}(this))},a.prototype.withHackValue=function(a){return"-webkit-background-clip"===a.prop&&"text"===a.value},a.prototype.disabled=function(a){var b;return null!=a._autoprefixerDisabled?a._autoprefixerDisabled:a.nodes?(b=void 0,a.each(function(a){return"comment"===a.type?"autoprefixer: off"===a.text?(b=!1,!1):"autoprefixer: on"===a.text?(b=!0,!1):void 0:void 0}),a._autoprefixerDisabled=null!=b?!b:a.parent?this.disabled(a.parent):!1):a._autoprefixerDisabled=this.disabled(a.parent)},a.prototype.reduceSpaces=function(a){var b,c,d,e;return e=!1,this.prefixes.group(a).up(function(a){return e=!0}),e?void 0:(c=a.style("before").split("\n"),d=c[c.length-1].length,b=!1,this.prefixes.group(a).down(function(a){var e;return c=a.style("before").split("\n"),e=c.length-1,c[e].length>d?(b===!1&&(b=c[e].length-d),c[e]=c[e].slice(0,-b),a.before=c.join("\n")):void 0}))},a}(),b.exports=c}).call(this)},{"./utils":46,"./value":47,"postcss/lib/vendor":113}],43:[function(a,b,c){(function(){var c,d,e,f,g,h,i=function(a,b){function c(){this.constructor=a}for(var d in b)j.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},j={}.hasOwnProperty;c=a("./prefixer"),h=a("./utils"),e=a("num2fraction"),f=/(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpi)/gi,g=/(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpi)/i,d=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return i(b,a),b.prototype.prefixName=function(a,b){return b="-moz-"===a?b+"--moz-device-pixel-ratio":a+b+"-device-pixel-ratio"},b.prototype.prefixQuery=function(a,b,c,d,f){return"dpi"===f&&(d=Number(d/96)),"-o-"===a&&(d=e(d)),this.prefixName(a,b)+c+d},b.prototype.clean=function(a){var b,c,d,e;if(!this.bad)for(this.bad=[],e=this.prefixes,b=0,c=e.length;c>b;b++)d=e[b],this.bad.push(this.prefixName(d,"min")),this.bad.push(this.prefixName(d,"max"));return a.params=h.editList(a.params,function(a){return function(b){return b.filter(function(b){return a.bad.every(function(a){return-1===b.indexOf(a)})})}}(this))},b.prototype.process=function(a){var b,c;return b=this.parentPrefix(a),c=b?[b]:this.prefixes,a.params=h.editList(a.params,function(b){return function(d,e){var i,j,k,l,m,n,o;for(i=0,k=d.length;k>i;i++)if(o=d[i],-1!==o.indexOf("min-resolution")||-1!==o.indexOf("max-resolution")){for(j=0,l=c.length;l>j;j++)m=c[j],("-moz-"!==m||-1===a.params.indexOf("dpi"))&&(n=o.replace(f,function(a){var c;return c=a.match(g),b.prefixQuery(m,c[1],c[2],c[3],c[4])}),e.push(n));e.push(o)}else e.push(o);return h.uniq(e)}}(this))},b}(c),b.exports=d}).call(this)},{"./prefixer":40,"./utils":46,num2fraction:95}],44:[function(a,b,c){(function(){var c,d,e,f,g,h=function(a,b){function c(){this.constructor=a}for(var d in b)i.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i={}.hasOwnProperty;d=a("./old-selector"),e=a("./prefixer"),c=a("./browsers"),g=a("./utils"),f=function(a){function b(a,b,c){this.name=a,this.prefixes=b,this.all=c,this.regexpCache={}}return h(b,a),b.prototype.check=function(a){return-1!==a.selector.indexOf(this.name)?!!a.selector.match(this.regexp()):!1},b.prototype.prefixed=function(a){return this.name.replace(/^([^\w]*)/,"$1"+a)},b.prototype.regexp=function(a){var b;return this.regexpCache[a]?this.regexpCache[a]:(b=a?this.prefixed(a):this.name,this.regexpCache[a]=RegExp("(^|[^:\"'=])"+g.escapeRegexp(b),"gi"))},b.prototype.possible=function(){return c.prefixes()},b.prototype.prefixeds=function(a){var b,c,d,e,f;if(a._autoprefixerPrefixeds)return a._autoprefixerPrefixeds;for(e={},f=this.possible(),b=0,c=f.length;c>b;b++)d=f[b],e[d]=this.replace(a.selector,d);return a._autoprefixerPrefixeds=e},b.prototype.already=function(a,b,c){var d,e,f,g,h;for(e=a.parent.index(a)-1;e>=0;){if(d=a.parent.nodes[e],"rule"!==d.type)return!1;h=!1;for(f in b)if(g=b[f],d.selector===g){if(c===f)return!0;h=!0;break}if(!h)return!1;e-=1}return!1},b.prototype.replace=function(a,b){return a.replace(this.regexp(),"$1"+this.prefixed(b))},b.prototype.add=function(a,b){var c,d;return d=this.prefixeds(a),this.already(a,d,b)?void 0:(c=this.clone(a,{selector:d[b]}),a.parent.insertBefore(a,c))},b.prototype.old=function(a){return new d(this,a)},b}(e),b.exports=f}).call(this)},{"./browsers":4,"./old-selector":38,"./prefixer":40,"./utils":46}],45:[function(a,b,c){(function(){var c,d,e,f,g,h,i,j,k;c=a("./prefixes"),e=a("./value"),k=a("./utils"),i=a("postcss"),h=a("postcss/lib/list"),j=/\(\s*([^\(\):]+)\s*:([^\)]+)/,g=/\(\s*([^\(\):]+)\s*:\s*(.+)\s*\)/g,f=/(not\s*)?\(\s*([^\(\):]+)\s*:\s*(.+?(?!\s*or\s*).+?)\s*\)*\s*\)\s*or\s*/gi,d=function(){function a(a){this.all=a}return a.prototype.virtual=function(a,b){var c;return c=i.parse("a{}").first,c.append({prop:a,value:b,before:""}),c},a.prototype.prefixed=function(a,b){var c,d,f,g,h,i,j,k,l;for(l=this.virtual(a,b),i=this.all.add[a],null!=i&&"function"==typeof i.process&&i.process(l.first),j=l.nodes,d=0,g=j.length;g>d;d++){for(c=j[d],k=this.all.values("add",a),f=0,h=k.length;h>f;f++)b=k[f],b.process(c);e.save(this.all,c)}return l.nodes},a.prototype.clean=function(a){return a.replace(f,function(b){return function(c){var d,e,f,g,h,i,l,m,n,o,p;if("not"===c.slice(0,3).toLowerCase())return c;if(l=c.match(j),d=l[0],i=l[1],p=l[2],o=b.all.unprefixed(i),(null!=(m=b.all.cleaner().remove[i])?m.remove:void 0)&&(e=new RegExp("(\\(|\\s)"+k.escapeRegexp(o)+":"),e.test(a)))return"";for(n=b.all.cleaner().values("remove",o),g=0,h=n.length;h>g;g++)if(f=n[g],f.check(p))return"";return c}}(this)).replace(/\(\s*\((.*)\)\s*\)/g,"($1)")},a.prototype.process=function(a){return a.params=this.clean(a.params),a.params=a.params.replace(g,function(a){return function(b,c,d){var e,f;return f=function(){var a,b,f,g;for(f=this.prefixed(c,d),g=[],a=0,b=f.length;b>a;a++)e=f[a],g.push("("+e.prop+": "+e.value+")");return g}.call(a),1===f.length?f[0]:"("+f.join(" or ")+")"}}(this))},a}(),b.exports=d}).call(this)},{"./prefixes":41,"./utils":46,"./value":47,postcss:107,"postcss/lib/list":102}],46:[function(a,b,c){(function(){var c;c=a("postcss/lib/list"),b.exports={error:function(a){var b;throw b=new Error(a),b.autoprefixer=!0,b},uniq:function(a){var b,c,d,e;for(b=[],d=0,e=a.length;e>d;d++)c=a[d],-1===b.indexOf(c)&&b.push(c);return b},removeNote:function(a){return-1===a.indexOf(" ")?a:a.split(" ")[0]},escapeRegexp:function(a){return a.replace(/[.?*+\^\$\[\]\\(){}|\-]/g,"\\$&")},regexp:function(a,b){return null==b&&(b=!0),b&&(a=this.escapeRegexp(a)),RegExp("(^|[\\s,(])("+a+"($|[\\s(,]))","gi")},editList:function(a,b){var d,e,f;return f=c.comma(a),d=b(f,[]),f===d?a:(e=a.match(/,\s*/),e=e?e[0]:", ",d.join(e))}}}).call(this)},{"postcss/lib/list":102}],47:[function(a,b,c){(function(){var c,d,e,f,g,h=function(a,b){function c(){this.constructor=a}for(var d in b)i.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i={}.hasOwnProperty;d=a("./prefixer"),c=a("./old-value"),f=a("./utils"),g=a("postcss/lib/vendor"),e=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return h(b,a),b.save=function(a,b){var c,d,e,f,h,i,j,k,l,m;i=b._autoprefixerValues,j=[];for(e in i)if(m=i[e],m!==b.value)if(h=g.prefix(b.prop), +h===e)j.push(b.value=m);else{if("-pie-"===h)continue;f=a.prefixed(b.prop,e),k=b.parent,k.every(function(a){return a.prop!==f})?(l=m.replace(/\s+/," "),c=k.some(function(a){return a.prop===b.prop&&a.value.replace(/\s+/," ")===l}),c?j.push(void 0):-1===m.indexOf("-webkit-filter")||"transition"!==b.prop&&"trasition-property"!==b.prop?(d=this.clone(b,{value:m}),j.push(b.parent.insertBefore(b,d))):j.push(b.value=m)):j.push(void 0)}return j},b.prototype.check=function(a){var b;return b=a.value,-1!==b.indexOf(this.name)?!!b.match(this.regexp()):!1},b.prototype.regexp=function(){return this.regexpCache||(this.regexpCache=f.regexp(this.name))},b.prototype.replace=function(a,b){return a.replace(this.regexp(),"$1"+b+"$2")},b.prototype.add=function(a,b){var c,d;return a._autoprefixerValues||(a._autoprefixerValues={}),d=a._autoprefixerValues[b]||(null!=(c=a._value)?c.raw:void 0)||a.value,d=this.replace(d,b),d?a._autoprefixerValues[b]=d:void 0},b.prototype.old=function(a){return new c(this.name,a+this.name)},b}(d),b.exports=e}).call(this)},{"./old-value":39,"./prefixer":40,"./utils":46,"postcss/lib/vendor":113}],48:[function(a,b,c){},{}],49:[function(a,b,c){function d(a,b){var c=this;if(!(c instanceof d))return new d(a,b);var e,f=typeof a;if("number"===f)e=+a;else if("string"===f)e=d.byteLength(a,b);else{if("object"!==f||null===a)throw new TypeError("must start with number, buffer, array or string");"Buffer"===a.type&&K(a.data)&&(a=a.data),e=+a.length}if(e>L)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+L.toString(16)+" bytes");0>e?e=0:e>>>=0,d.TYPED_ARRAY_SUPPORT?c=d._augment(new Uint8Array(e)):(c.length=e,c._isBuffer=!0);var g;if(d.TYPED_ARRAY_SUPPORT&&"number"==typeof a.byteLength)c._set(a);else if(A(a))if(d.isBuffer(a))for(g=0;e>g;g++)c[g]=a.readUInt8(g);else for(g=0;e>g;g++)c[g]=(a[g]%256+256)%256;else if("string"===f)c.write(a,0,b);else if("number"===f&&!d.TYPED_ARRAY_SUPPORT)for(g=0;e>g;g++)c[g]=0;return e>0&&e<=d.poolSize&&(c.parent=M),c}function e(a,b){if(!(this instanceof e))return new e(a,b);var c=new d(a,b);return delete c.parent,c}function f(a,b,c,d){c=Number(c)||0;var e=a.length-c;d?(d=Number(d),d>e&&(d=e)):d=e;var f=b.length;if(f%2!==0)throw new Error("Invalid hex string");d>f/2&&(d=f/2);for(var g=0;d>g;g++){var h=parseInt(b.substr(2*g,2),16);if(isNaN(h))throw new Error("Invalid hex string");a[c+g]=h}return g}function g(a,b,c,d){var e=G(C(b,a.length-c),a,c,d);return e}function h(a,b,c,d){var e=G(D(b),a,c,d);return e}function i(a,b,c,d){return h(a,b,c,d)}function j(a,b,c,d){var e=G(F(b),a,c,d);return e}function k(a,b,c,d){var e=G(E(b,a.length-c),a,c,d);return e}function l(a,b,c){return 0===b&&c===a.length?I.fromByteArray(a):I.fromByteArray(a.slice(b,c))}function m(a,b,c){var d="",e="";c=Math.min(a.length,c);for(var f=b;c>f;f++)a[f]<=127?(d+=H(e)+String.fromCharCode(a[f]),e=""):e+="%"+a[f].toString(16);return d+H(e)}function n(a,b,c){var d="";c=Math.min(a.length,c);for(var e=b;c>e;e++)d+=String.fromCharCode(127&a[e]);return d}function o(a,b,c){var d="";c=Math.min(a.length,c);for(var e=b;c>e;e++)d+=String.fromCharCode(a[e]);return d}function p(a,b,c){var d=a.length;(!b||0>b)&&(b=0),(!c||0>c||c>d)&&(c=d);for(var e="",f=b;c>f;f++)e+=B(a[f]);return e}function q(a,b,c){for(var d=a.slice(b,c),e="",f=0;fa)throw new RangeError("offset is not uint");if(a+b>c)throw new RangeError("Trying to access beyond buffer length")}function s(a,b,c,e,f,g){if(!d.isBuffer(a))throw new TypeError("buffer must be a Buffer instance");if(b>f||g>b)throw new RangeError("value is out of bounds");if(c+e>a.length)throw new RangeError("index out of range")}function t(a,b,c,d){0>b&&(b=65535+b+1);for(var e=0,f=Math.min(a.length-c,2);f>e;e++)a[c+e]=(b&255<<8*(d?e:1-e))>>>8*(d?e:1-e)}function u(a,b,c,d){0>b&&(b=4294967295+b+1);for(var e=0,f=Math.min(a.length-c,4);f>e;e++)a[c+e]=b>>>8*(d?e:3-e)&255}function v(a,b,c,d,e,f){if(b>e||f>b)throw new RangeError("value is out of bounds");if(c+d>a.length)throw new RangeError("index out of range");if(0>c)throw new RangeError("index out of range")}function w(a,b,c,d,e){return e||v(a,b,c,4,3.4028234663852886e38,-3.4028234663852886e38),J.write(a,b,c,d,23,4),c+4}function x(a,b,c,d,e){return e||v(a,b,c,8,1.7976931348623157e308,-1.7976931348623157e308),J.write(a,b,c,d,52,8),c+8}function y(a){if(a=z(a).replace(O,""),a.length<2)return"";for(;a.length%4!==0;)a+="=";return a}function z(a){return a.trim?a.trim():a.replace(/^\s+|\s+$/g,"")}function A(a){return K(a)||d.isBuffer(a)||a&&"object"==typeof a&&"number"==typeof a.length}function B(a){return 16>a?"0"+a.toString(16):a.toString(16)}function C(a,b){b=b||1/0;for(var c,d=a.length,e=null,f=[],g=0;d>g;g++){if(c=a.charCodeAt(g),c>55295&&57344>c){if(!e){if(c>56319){(b-=3)>-1&&f.push(239,191,189);continue}if(g+1===d){(b-=3)>-1&&f.push(239,191,189);continue}e=c;continue}if(56320>c){(b-=3)>-1&&f.push(239,191,189),e=c;continue}c=e-55296<<10|c-56320|65536,e=null}else e&&((b-=3)>-1&&f.push(239,191,189),e=null);if(128>c){if((b-=1)<0)break;f.push(c)}else if(2048>c){if((b-=2)<0)break;f.push(c>>6|192,63&c|128)}else if(65536>c){if((b-=3)<0)break;f.push(c>>12|224,c>>6&63|128,63&c|128)}else{if(!(2097152>c))throw new Error("Invalid code point");if((b-=4)<0)break;f.push(c>>18|240,c>>12&63|128,c>>6&63|128,63&c|128)}}return f}function D(a){for(var b=[],c=0;c>8,e=c%256,f.push(e),f.push(d);return f}function F(a){return I.toByteArray(y(a))}function G(a,b,c,d){for(var e=0;d>e&&!(e+c>=b.length||e>=a.length);e++)b[e+c]=a[e];return e}function H(a){try{return decodeURIComponent(a)}catch(b){return String.fromCharCode(65533)}}/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +var I=a("base64-js"),J=a("ieee754"),K=a("is-array");c.Buffer=d,c.SlowBuffer=e,c.INSPECT_MAX_BYTES=50,d.poolSize=8192;var L=1073741823,M={};d.TYPED_ARRAY_SUPPORT=function(){try{var a=new ArrayBuffer(0),b=new Uint8Array(a);return b.foo=function(){return 42},42===b.foo()&&"function"==typeof b.subarray&&0===new Uint8Array(1).subarray(1,1).byteLength}catch(c){return!1}}(),d.isBuffer=function(a){return!(null==a||!a._isBuffer)},d.compare=function(a,b){if(!d.isBuffer(a)||!d.isBuffer(b))throw new TypeError("Arguments must be Buffers");if(a===b)return 0;for(var c=a.length,e=b.length,f=0,g=Math.min(c,e);g>f&&a[f]===b[f];f++);return f!==g&&(c=a[f],e=b[f]),e>c?-1:c>e?1:0},d.isEncoding=function(a){switch(String(a).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},d.concat=function(a,b){if(!K(a))throw new TypeError("list argument must be an Array of Buffers.");if(0===a.length)return new d(0);if(1===a.length)return a[0];var c;if(void 0===b)for(b=0,c=0;c>>1;break;case"utf8":case"utf-8":c=C(a).length;break;case"base64":c=F(a).length;break;default:c=a.length}return c},d.prototype.length=void 0,d.prototype.parent=void 0,d.prototype.toString=function(a,b,c){var d=!1;if(b>>>=0,c=void 0===c||c===1/0?this.length:c>>>0,a||(a="utf8"),0>b&&(b=0),c>this.length&&(c=this.length),b>=c)return"";for(;;)switch(a){case"hex":return p(this,b,c);case"utf8":case"utf-8":return m(this,b,c);case"ascii":return n(this,b,c);case"binary":return o(this,b,c);case"base64":return l(this,b,c);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return q(this,b,c);default:if(d)throw new TypeError("Unknown encoding: "+a);a=(a+"").toLowerCase(),d=!0}},d.prototype.equals=function(a){if(!d.isBuffer(a))throw new TypeError("Argument must be a Buffer");return this===a?!0:0===d.compare(this,a)},d.prototype.inspect=function(){var a="",b=c.INSPECT_MAX_BYTES;return this.length>0&&(a=this.toString("hex",0,b).match(/.{2}/g).join(" "),this.length>b&&(a+=" ... ")),""},d.prototype.compare=function(a){if(!d.isBuffer(a))throw new TypeError("Argument must be a Buffer");return this===a?0:d.compare(this,a)},d.prototype.indexOf=function(a,b){function c(a,b,c){for(var d=-1,e=0;c+e2147483647?b=2147483647:-2147483648>b&&(b=-2147483648),b>>=0,0===this.length)return-1;if(b>=this.length)return-1;if(0>b&&(b=Math.max(this.length+b,0)),"string"==typeof a)return 0===a.length?-1:String.prototype.indexOf.call(this,a,b);if(d.isBuffer(a))return c(this,a,b);if("number"==typeof a)return d.TYPED_ARRAY_SUPPORT&&"function"===Uint8Array.prototype.indexOf?Uint8Array.prototype.indexOf.call(this,a,b):c(this,[a],b);throw new TypeError("val must be string, number or Buffer")},d.prototype.get=function(a){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(a)},d.prototype.set=function(a,b){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(a,b)},d.prototype.write=function(a,b,c,d){if(isFinite(b))isFinite(c)||(d=c,c=void 0);else{var e=d;d=b,b=c,c=e}if(b=Number(b)||0,0>c||0>b||b>this.length)throw new RangeError("attempt to write outside buffer bounds");var l=this.length-b;c?(c=Number(c),c>l&&(c=l)):c=l,d=String(d||"utf8").toLowerCase();var m;switch(d){case"hex":m=f(this,a,b,c);break;case"utf8":case"utf-8":m=g(this,a,b,c);break;case"ascii":m=h(this,a,b,c);break;case"binary":m=i(this,a,b,c);break;case"base64":m=j(this,a,b,c);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":m=k(this,a,b,c);break;default:throw new TypeError("Unknown encoding: "+d)}return m},d.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},d.prototype.slice=function(a,b){var c=this.length;a=~~a,b=void 0===b?c:~~b,0>a?(a+=c,0>a&&(a=0)):a>c&&(a=c),0>b?(b+=c,0>b&&(b=0)):b>c&&(b=c),a>b&&(b=a);var e;if(d.TYPED_ARRAY_SUPPORT)e=d._augment(this.subarray(a,b));else{var f=b-a;e=new d(f,void 0);for(var g=0;f>g;g++)e[g]=this[g+a]}return e.length&&(e.parent=this.parent||this),e},d.prototype.readUIntLE=function(a,b,c){a>>>=0,b>>>=0,c||r(a,b,this.length);for(var d=this[a],e=1,f=0;++f>>=0,b>>>=0,c||r(a,b,this.length);for(var d=this[a+--b],e=1;b>0&&(e*=256);)d+=this[a+--b]*e;return d},d.prototype.readUInt8=function(a,b){return b||r(a,1,this.length),this[a]},d.prototype.readUInt16LE=function(a,b){return b||r(a,2,this.length),this[a]|this[a+1]<<8},d.prototype.readUInt16BE=function(a,b){return b||r(a,2,this.length),this[a]<<8|this[a+1]},d.prototype.readUInt32LE=function(a,b){return b||r(a,4,this.length),(this[a]|this[a+1]<<8|this[a+2]<<16)+16777216*this[a+3]},d.prototype.readUInt32BE=function(a,b){return b||r(a,4,this.length),16777216*this[a]+(this[a+1]<<16|this[a+2]<<8|this[a+3])},d.prototype.readIntLE=function(a,b,c){a>>>=0,b>>>=0,c||r(a,b,this.length);for(var d=this[a],e=1,f=0;++f=e&&(d-=Math.pow(2,8*b)),d},d.prototype.readIntBE=function(a,b,c){a>>>=0,b>>>=0,c||r(a,b,this.length);for(var d=b,e=1,f=this[a+--d];d>0&&(e*=256);)f+=this[a+--d]*e;return e*=128,f>=e&&(f-=Math.pow(2,8*b)),f},d.prototype.readInt8=function(a,b){return b||r(a,1,this.length),128&this[a]?-1*(255-this[a]+1):this[a]},d.prototype.readInt16LE=function(a,b){b||r(a,2,this.length);var c=this[a]|this[a+1]<<8;return 32768&c?4294901760|c:c},d.prototype.readInt16BE=function(a,b){b||r(a,2,this.length);var c=this[a+1]|this[a]<<8;return 32768&c?4294901760|c:c},d.prototype.readInt32LE=function(a,b){return b||r(a,4,this.length),this[a]|this[a+1]<<8|this[a+2]<<16|this[a+3]<<24},d.prototype.readInt32BE=function(a,b){return b||r(a,4,this.length),this[a]<<24|this[a+1]<<16|this[a+2]<<8|this[a+3]},d.prototype.readFloatLE=function(a,b){return b||r(a,4,this.length),J.read(this,a,!0,23,4)},d.prototype.readFloatBE=function(a,b){return b||r(a,4,this.length),J.read(this,a,!1,23,4)},d.prototype.readDoubleLE=function(a,b){return b||r(a,8,this.length),J.read(this,a,!0,52,8)},d.prototype.readDoubleBE=function(a,b){return b||r(a,8,this.length),J.read(this,a,!1,52,8)},d.prototype.writeUIntLE=function(a,b,c,d){a=+a,b>>>=0,c>>>=0,d||s(this,a,b,c,Math.pow(2,8*c),0);var e=1,f=0;for(this[b]=255&a;++f>>0&255;return b+c},d.prototype.writeUIntBE=function(a,b,c,d){a=+a,b>>>=0,c>>>=0,d||s(this,a,b,c,Math.pow(2,8*c),0);var e=c-1,f=1;for(this[b+e]=255&a;--e>=0&&(f*=256);)this[b+e]=a/f>>>0&255;return b+c},d.prototype.writeUInt8=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,1,255,0),d.TYPED_ARRAY_SUPPORT||(a=Math.floor(a)),this[b]=a,b+1},d.prototype.writeUInt16LE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,2,65535,0),d.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8):t(this,a,b,!0),b+2},d.prototype.writeUInt16BE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,2,65535,0),d.TYPED_ARRAY_SUPPORT?(this[b]=a>>>8,this[b+1]=a):t(this,a,b,!1),b+2},d.prototype.writeUInt32LE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[b+3]=a>>>24,this[b+2]=a>>>16,this[b+1]=a>>>8,this[b]=a):u(this,a,b,!0),b+4},d.prototype.writeUInt32BE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[b]=a>>>24,this[b+1]=a>>>16,this[b+2]=a>>>8,this[b+3]=a):u(this,a,b,!1),b+4},d.prototype.writeIntLE=function(a,b,c,d){a=+a,b>>>=0,d||s(this,a,b,c,Math.pow(2,8*c-1)-1,-Math.pow(2,8*c-1));var e=0,f=1,g=0>a?1:0;for(this[b]=255&a;++e>0)-g&255;return b+c},d.prototype.writeIntBE=function(a,b,c,d){a=+a,b>>>=0,d||s(this,a,b,c,Math.pow(2,8*c-1)-1,-Math.pow(2,8*c-1));var e=c-1,f=1,g=0>a?1:0;for(this[b+e]=255&a;--e>=0&&(f*=256);)this[b+e]=(a/f>>0)-g&255;return b+c},d.prototype.writeInt8=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,1,127,-128),d.TYPED_ARRAY_SUPPORT||(a=Math.floor(a)),0>a&&(a=255+a+1),this[b]=a,b+1},d.prototype.writeInt16LE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8):t(this,a,b,!0),b+2},d.prototype.writeInt16BE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[b]=a>>>8,this[b+1]=a):t(this,a,b,!1),b+2},d.prototype.writeInt32LE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,4,2147483647,-2147483648),d.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8,this[b+2]=a>>>16,this[b+3]=a>>>24):u(this,a,b,!0),b+4},d.prototype.writeInt32BE=function(a,b,c){return a=+a,b>>>=0,c||s(this,a,b,4,2147483647,-2147483648),0>a&&(a=4294967295+a+1),d.TYPED_ARRAY_SUPPORT?(this[b]=a>>>24,this[b+1]=a>>>16,this[b+2]=a>>>8,this[b+3]=a):u(this,a,b,!1),b+4},d.prototype.writeFloatLE=function(a,b,c){return w(this,a,b,!0,c)},d.prototype.writeFloatBE=function(a,b,c){return w(this,a,b,!1,c)},d.prototype.writeDoubleLE=function(a,b,c){return x(this,a,b,!0,c)},d.prototype.writeDoubleBE=function(a,b,c){return x(this,a,b,!1,c)},d.prototype.copy=function(a,b,c,e){if(c||(c=0),e||0===e||(e=this.length),b>=a.length&&(b=a.length),b||(b=0),e>0&&c>e&&(e=c),e===c)return 0;if(0===a.length||0===this.length)return 0;if(0>b)throw new RangeError("targetStart out of bounds");if(0>c||c>=this.length)throw new RangeError("sourceStart out of bounds");if(0>e)throw new RangeError("sourceEnd out of bounds");e>this.length&&(e=this.length),a.length-bf||!d.TYPED_ARRAY_SUPPORT)for(var g=0;f>g;g++)a[g+b]=this[g+c];else a._set(this.subarray(c,c+f),b);return f},d.prototype.fill=function(a,b,c){if(a||(a=0),b||(b=0),c||(c=this.length),b>c)throw new RangeError("end < start");if(c!==b&&0!==this.length){if(0>b||b>=this.length)throw new RangeError("start out of bounds");if(0>c||c>this.length)throw new RangeError("end out of bounds");var d;if("number"==typeof a)for(d=b;c>d;d++)this[d]=a;else{var e=C(a.toString()),f=e.length;for(d=b;c>d;d++)this[d]=e[d%f]}return this}},d.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(d.TYPED_ARRAY_SUPPORT)return new d(this).buffer;for(var a=new Uint8Array(this.length),b=0,c=a.length;c>b;b+=1)a[b]=this[b];return a.buffer}throw new TypeError("Buffer.toArrayBuffer not supported in this browser")};var N=d.prototype;d._augment=function(a){return a.constructor=d,a._isBuffer=!0,a._set=a.set,a.get=N.get,a.set=N.set,a.write=N.write,a.toString=N.toString,a.toLocaleString=N.toString,a.toJSON=N.toJSON,a.equals=N.equals,a.compare=N.compare,a.indexOf=N.indexOf,a.copy=N.copy,a.slice=N.slice,a.readUIntLE=N.readUIntLE,a.readUIntBE=N.readUIntBE,a.readUInt8=N.readUInt8,a.readUInt16LE=N.readUInt16LE,a.readUInt16BE=N.readUInt16BE,a.readUInt32LE=N.readUInt32LE,a.readUInt32BE=N.readUInt32BE,a.readIntLE=N.readIntLE,a.readIntBE=N.readIntBE,a.readInt8=N.readInt8,a.readInt16LE=N.readInt16LE,a.readInt16BE=N.readInt16BE,a.readInt32LE=N.readInt32LE,a.readInt32BE=N.readInt32BE,a.readFloatLE=N.readFloatLE,a.readFloatBE=N.readFloatBE,a.readDoubleLE=N.readDoubleLE,a.readDoubleBE=N.readDoubleBE,a.writeUInt8=N.writeUInt8,a.writeUIntLE=N.writeUIntLE,a.writeUIntBE=N.writeUIntBE,a.writeUInt16LE=N.writeUInt16LE,a.writeUInt16BE=N.writeUInt16BE,a.writeUInt32LE=N.writeUInt32LE,a.writeUInt32BE=N.writeUInt32BE,a.writeIntLE=N.writeIntLE,a.writeIntBE=N.writeIntBE,a.writeInt8=N.writeInt8,a.writeInt16LE=N.writeInt16LE,a.writeInt16BE=N.writeInt16BE,a.writeInt32LE=N.writeInt32LE,a.writeInt32BE=N.writeInt32BE,a.writeFloatLE=N.writeFloatLE,a.writeFloatBE=N.writeFloatBE,a.writeDoubleLE=N.writeDoubleLE,a.writeDoubleBE=N.writeDoubleBE,a.fill=N.fill,a.inspect=N.inspect,a.toArrayBuffer=N.toArrayBuffer,a};var O=/[^+\/0-9A-z\-]/g},{"base64-js":50,ieee754:51,"is-array":52}],50:[function(a,b,c){var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(a){"use strict";function b(a){var b=a.charCodeAt(0);return b===g||b===l?62:b===h||b===m?63:i>b?-1:i+10>b?b-i+26+26:k+26>b?b-k:j+26>b?b-j+26:void 0}function c(a){function c(a){j[l++]=a}var d,e,g,h,i,j;if(a.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var k=a.length;i="="===a.charAt(k-2)?2:"="===a.charAt(k-1)?1:0,j=new f(3*a.length/4-i),g=i>0?a.length-4:a.length;var l=0;for(d=0,e=0;g>d;d+=4,e+=3)h=b(a.charAt(d))<<18|b(a.charAt(d+1))<<12|b(a.charAt(d+2))<<6|b(a.charAt(d+3)),c((16711680&h)>>16),c((65280&h)>>8),c(255&h);return 2===i?(h=b(a.charAt(d))<<2|b(a.charAt(d+1))>>4,c(255&h)):1===i&&(h=b(a.charAt(d))<<10|b(a.charAt(d+1))<<4|b(a.charAt(d+2))>>2,c(h>>8&255),c(255&h)),j}function e(a){function b(a){return d.charAt(a)}function c(a){return b(a>>18&63)+b(a>>12&63)+b(a>>6&63)+b(63&a)}var e,f,g,h=a.length%3,i="";for(e=0,g=a.length-h;g>e;e+=3)f=(a[e]<<16)+(a[e+1]<<8)+a[e+2],i+=c(f);switch(h){case 1:f=a[a.length-1],i+=b(f>>2),i+=b(f<<4&63),i+="==";break;case 2:f=(a[a.length-2]<<8)+a[a.length-1],i+=b(f>>10),i+=b(f>>4&63),i+=b(f<<2&63),i+="="}return i}var f="undefined"!=typeof Uint8Array?Uint8Array:Array,g="+".charCodeAt(0),h="/".charCodeAt(0),i="0".charCodeAt(0),j="a".charCodeAt(0),k="A".charCodeAt(0),l="-".charCodeAt(0),m="_".charCodeAt(0);a.toByteArray=c,a.fromByteArray=e}("undefined"==typeof c?this.base64js={}:c)},{}],51:[function(a,b,c){c.read=function(a,b,c,d,e){var f,g,h=8*e-d-1,i=(1<>1,k=-7,l=c?e-1:0,m=c?-1:1,n=a[b+l];for(l+=m,f=n&(1<<-k)-1,n>>=-k,k+=h;k>0;f=256*f+a[b+l],l+=m,k-=8);for(g=f&(1<<-k)-1,f>>=-k,k+=d;k>0;g=256*g+a[b+l],l+=m,k-=8);if(0===f)f=1-j;else{if(f===i)return g?NaN:(n?-1:1)*(1/0);g+=Math.pow(2,d),f-=j}return(n?-1:1)*g*Math.pow(2,f-d)},c.write=function(a,b,c,d,e,f){var g,h,i,j=8*f-e-1,k=(1<>1,m=23===e?Math.pow(2,-24)-Math.pow(2,-77):0,n=d?0:f-1,o=d?1:-1,p=0>b||0===b&&0>1/b?1:0;for(b=Math.abs(b),isNaN(b)||b===1/0?(h=isNaN(b)?1:0,g=k):(g=Math.floor(Math.log(b)/Math.LN2),b*(i=Math.pow(2,-g))<1&&(g--,i*=2),b+=g+l>=1?m/i:m*Math.pow(2,1-l),b*i>=2&&(g++,i/=2),g+l>=k?(h=0,g=k):g+l>=1?(h=(b*i-1)*Math.pow(2,e),g+=l):(h=b*Math.pow(2,l-1)*Math.pow(2,e),g=0));e>=8;a[c+n]=255&h,n+=o,h/=256,e-=8);for(g=g<0;a[c+n]=255&g,n+=o,g/=256,j-=8);a[c+n-o]|=128*p}},{}],52:[function(a,b,c){var d=Array.isArray,e=Object.prototype.toString;b.exports=d||function(a){return!!a&&"[object Array]"==e.call(a)}},{}],53:[function(a,b,c){(function(a){function b(a,b){for(var c=0,d=a.length-1;d>=0;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function d(a,b){if(a.filter)return a.filter(b);for(var c=[],d=0;d=-1&&!e;f--){var g=f>=0?arguments[f]:a.cwd();if("string"!=typeof g)throw new TypeError("Arguments to path.resolve must be strings");g&&(c=g+"/"+c,e="/"===g.charAt(0))}return c=b(d(c.split("/"),function(a){return!!a}),!e).join("/"),(e?"/":"")+c||"."},c.normalize=function(a){var e=c.isAbsolute(a),f="/"===g(a,-1);return a=b(d(a.split("/"),function(a){return!!a}),!e).join("/"),a||e||(a="."),a&&f&&(a+="/"),(e?"/":"")+a},c.isAbsolute=function(a){return"/"===a.charAt(0)},c.join=function(){var a=Array.prototype.slice.call(arguments,0);return c.normalize(d(a,function(a,b){if("string"!=typeof a)throw new TypeError("Arguments to path.join must be strings");return a}).join("/"))},c.relative=function(a,b){function d(a){for(var b=0;b=0&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=c.resolve(a).substr(1),b=c.resolve(b).substr(1);for(var e=d(a.split("/")),f=d(b.split("/")),g=Math.min(e.length,f.length),h=g,i=0;g>i;i++)if(e[i]!==f[i]){h=i;break}for(var j=[],i=h;ib&&(b=a.length+b),a.substr(b,c)}}).call(this,a("_process"))},{_process:54}],54:[function(a,b,c){function d(){if(!h){h=!0;for(var a,b=g.length;b;){a=g,g=[];for(var c=-1;++c 1%","last 2 versions","Firefox ESR","Opera 12.1"],h.major=["safari","opera","ios_saf","ie_mob","ie","firefox","chrome"],h.aliases={fx:"firefox",ff:"firefox",ios:"ios_saf",explorer:"ie",blackberry:"bb",explorermobile:"ie_mob",operamini:"op_mini",operamobile:"op_mob",chromeandroid:"and_chr",firefoxandroid:"and_ff"},h.versionAliases={},h.byName=function(a){a=a.toLowerCase(),a=h.aliases[a]||a;var b=h.data[a];if(!b)throw"Unknown browser "+a;return b},h.readConfig=function(a){if(a===!1)return!1;if(!f.readFileSync)return!1;"undefined"==typeof a&&(a=".");for(var b,c=e.resolve(a).split(e.sep);c.length;){if(b=c.concat(["browserslist"]).join(e.sep),f.existsSync(b)&&f.lstatSync(b).isFile())return h.parseConfig(f.readFileSync(b));c.pop()}return!1},h.parseConfig=function(a){return a.toString().replace(/#[^\n]*/g,"").split(/\n/).map(function(a){return a.trim()}).filter(function(a){return""!==a})},h.queries={lastVersions:{regexp:/^last (\d+) versions?$/i,select:function(a){var b=[];return h.major.forEach(function(c){var d=h.byName(c),e=d.released.slice(-a);e=e.map(function(a){return d.name+" "+a}),b=b.concat(e)}),b}},lastByBrowser:{regexp:/^last (\d+) (\w+) versions?$/i,select:function(a,b){var c=h.byName(b);return c.released.slice(-a).map(function(a){return c.name+" "+a})}},globalStatistics:{regexp:/^> (\d+\.?\d*)%$/,select:function(a){a=parseFloat(a);var b=[];for(var c in h.usage.global)h.usage.global[c]>a&&b.push(c);return b}},countryStatistics:{regexp:/^> (\d+\.?\d*)% in (\w\w)$/,select:function(b,c){b=parseFloat(b),c=c.toUpperCase();var d=[],e=h.usage[c];if(!e){e={};var f=a("caniuse-db/region-usage-json/"+c);for(var g in f.data)j(e,g,f.data[g]);h.usage[c]=e}for(var i in e)e[i]>b&&d.push(i);return d}},versions:{regexp:/^(\w+) (>=?|<=?)\s*([\d\.]+)/,select:function(a,b,c){var d=h.byName(a);c=parseFloat(c);var e;return">"==b?e=function(a){return parseFloat(a)>c}:">="==b?e=function(a){return parseFloat(a)>=c}:"<"==b?e=function(a){return parseFloat(a)",ie_id:"",chrome_id:""},audio:{title:"Audio element",description:"Method of playing sound on webpages (without requiring a plug-in).",spec:"https://html.spec.whatwg.org/multipage/embedded-content.html#the-audio-element",status:"ls",links:[{url:"http://html5doctor.com/native-audio-in-the-browser/",title:"HTML5 Doctor article"},{url:"https://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/",title:"Detailed article on video/audio elements"},{url:"http://www.jplayer.org/latest/demos/",title:"Demos of audio player that uses the audio element"},{url:"http://24ways.org/2010/the-state-of-html5-audio",title:"Detailed article on support"},{url:"http://textopia.org/androidsoundformats.html",title:"File format test page"},{url:"http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio",title:"The State of HTML5 Audio"},{url:"https://raw.github.com/phiggins42/has.js/master/detect/audio.js#audio",title:"has.js test"},{url:"http://docs.webplatform.org/wiki/html/elements/audio",title:"WebPlatform Docs"}],categories:["HTML5"],stats:{ie:{5.5:"n",6:"n",7:"n",8:"n",9:"y",10:"y",11:"y",TP:"y"},firefox:{2:"n",3:"n",3.5:"y",3.6:"y",4:"y",5:"y",6:"y",7:"y",8:"y",9:"y",10:"y",11:"y",12:"y",13:"y",14:"y",15:"y",16:"y",17:"y",18:"y",19:"y",20:"y",21:"y",22:"y",23:"y",24:"y",25:"y",26:"y",27:"y",28:"y",29:"y",30:"y",31:"y",32:"y",33:"y",34:"y",35:"y",36:"y",37:"y",38:"y",39:"y",40:"y"},chrome:{4:"y",5:"y",6:"y",7:"y",8:"y",9:"y",10:"y",11:"y",12:"y",13:"y",14:"y",15:"y",16:"y",17:"y",18:"y",19:"y",20:"y",21:"y",22:"y",23:"y",24:"y",25:"y",26:"y",27:"y",28:"y",29:"y",30:"y",31:"y",32:"y",33:"y",34:"y",35:"y",36:"y",37:"y",38:"y",39:"y",40:"y",41:"y",42:"y",43:"y",44:"y"},safari:{3.1:"n",3.2:"n",4:"y",5:"y",5.1:"y",6:"y",6.1:"y",7:"y",7.1:"y",8:"y"},opera:{9:"n","9.5-9.6":"a","10.0-10.1":"a",10.5:"y",10.6:"y",11:"y",11.1:"y",11.5:"y",11.6:"y",12:"y",12.1:"y",15:"y",16:"y",17:"y",18:"y",19:"y",20:"y",21:"y",22:"y",23:"y",24:"y",25:"y",26:"y",27:"y",28:"y",29:"y"},ios_saf:{3.2:"n","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y",8:"y","8.1-8.3":"y"},op_mini:{"5.0-8.0":"n"},android:{2.1:"n",2.2:"n",2.3:"y",3:"y",4:"y",4.1:"y","4.2-4.3":"y",4.4:"y","4.4.3-4.4.4":"y",40:"y"},bb:{7:"y",10:"y"},op_mob:{10:"n",11:"y",11.1:"y",11.5:"y",12:"y",12.1:"y",24:"y"},and_chr:{41:"y"},and_ff:{36:"y"},ie_mob:{10:"y",11:"y"},and_uc:{9.9:"y"}},notes:"",notes_by_num:{},usage_perc_y:91.84,usage_perc_a:.03,ucprefix:!1,parent:"",keywords:"