+ Note that GW2 Raidar only requires the keys to authenticate your ownership of
+ a GW2 account. Therefore, you only need the default "account" permission.
+
diff --git a/raidar/templates/raidar/encounter.html b/raidar/templates/raidar/encounter.html
new file mode 100644
index 00000000..9606b540
--- /dev/null
+++ b/raidar/templates/raidar/encounter.html
@@ -0,0 +1,78 @@
+
+
diff --git a/raidar/templates/raidar/info_about.html b/raidar/templates/raidar/info_about.html
new file mode 100644
index 00000000..0d633b99
--- /dev/null
+++ b/raidar/templates/raidar/info_about.html
@@ -0,0 +1,51 @@
+
Donate
+
As with any website, hosting and server costs are always at play. If you love this site, why not consider donating? A one off donation of a dollar or ten dollars is a huge help in providing this website for free and ad-free to the community.
+
+
+
The Team
+
+
Big Bossy Boots
+
+ Name: Merforga
+ In Game: Merforga.4731
+ Reddit: u/merforga1
+ Email: admin@gw2raidar.com
+ Skills: Bossing people around, making unrealistic demands, financier
+
+
+
Head Code Monkey
+
+ Name: Delight/Amadan
+ In Game: AmadanMath.2409
+ Reddit: u/Amadan
+ Skills: Goofs up a lot, releases things into the wild
+
+
+
Code Monkey 1
+
+ Name: Toeofdoom / Veranaday
+ In Game: toeofdoom.6152
+ Reddit: u/Toeofdoom
+ Skills: Invents and builds data engines
+
+
+
Code Monkey 2
+
+
+
Legalese Stuff
+
GW2 Raidar uses a combination of assets from the Official Guild Wars 2 website (guildwars2.com) as well as the Guild Wars 2 Wiki (wiki.guildwars2.com). Usage of assets and copyright fall under their respective website license agreements as per below
+
+
Content provided by individual contributors, which is original and does not infringe upon the intellectual property rights of any third party, is available under the GNU Free Documentation License 1.2 (GFDL).
+
+
Content obtained from Guild Wars 2, its web sites, manuals and guides, concept art and renderings, press and fansite kits, and other such copyrighted material, may also be available from this site. All rights, title and interest in and to such content remains with ArenaNet or NCsoft, as applicable, and such content is not licensed pursuant to the GFDL
+
diff --git a/raidar/templates/raidar/info_contact.html b/raidar/templates/raidar/info_contact.html
new file mode 100644
index 00000000..78f4adaf
--- /dev/null
+++ b/raidar/templates/raidar/info_contact.html
@@ -0,0 +1,21 @@
+
Contact
+
+
diff --git a/raidar/templates/raidar/info_help.html b/raidar/templates/raidar/info_help.html
new file mode 100644
index 00000000..006b32c7
--- /dev/null
+++ b/raidar/templates/raidar/info_help.html
@@ -0,0 +1,92 @@
+{% load staticfiles %}
+
What is GW2 Raidar?
+
+
With the advent and increased usage of DPS meters, there have been a number of different parsers released to analyse, in detail, combat statistics and logs for post review.
+
+
While current encounter reports are great, they currently lack one thing, context. GW2 Raidar’s approach to log parsing is slightly different. By retaining high level data about uploaded encounters, GW2 Raidar will allow you compare your individual and squad performance against everyone else’s as an average which will allow you to further analyse your post fight logs.
+
+
With GW2 Raidar you can:
+
+
+ See at a top level your performance and your squad’s performance at a glance
+ See how your and your squads metrics compare to current averages
+ See what the top group metrics and what professions are most popular for each encounter
+ Upload 1 log per encounter and have everyone in the squad access the encounter automatically via their GW2 Raidar account
+ Link multiple Guild Wars 2 accounts to a single GW2 Raidar account for a consolidated single view across all your raid characters
+ See your personal raid statistics as a whole
+ Redownload previous encounter log files to parse through another website or application.
+
+
+
Getting Started
+
+
Getting started is easy. Simply create a new account on the website. You will need to provide in addition to your desired login credentials, your Guild Wars 2 API Key to confirm your ownership of a Guild Wars 2 Account.
+
+
GW2 Raidar will automatically get your GW2 account name and associated characters. Any encounters that have been uploaded with your GW2 account in them will show up straight away in your encounters page.
+
+
Uploading Logs
+
+
To upload your logs, simply drag and drop your log files into the browser window. GW2 Raidar supports both uncompressed and compressed logs. You can access results of each log by clicking on the name in the encounter list.
+
+
Due to the need to update global statistics, GW2 Raidar utilises a batch processing system. As such, analysing may take a few minutes, however once a log is uploaded, it will always be analysed, even if you leave the website!
+
+
Interpreting the numbers
+
+
On each Encounter page, you’ll be shown a few different sections of statistics as per below. For all statistics (with the exception of Party stats), the following colour codes apply:
+
+
+ Red to yellow to green: Visually compares your figure with global average. Red = Worse than average, Yellow = On par, Green = Better than average
+ Purple: Visually represent the current average
+
+
+
Squad
+
+
+
Shows total squad values. The first number denotes your squad’s totals with the second number denoting the current global average
+
+
Party
+
+
+
Allows you compare individual party information to see performance of each sub group. These have no averages.
+
+
Individual
+
+
+
Shows individual values. The first number denotes individual values with the second number denoting the current global average. All averages are based on the detected archetype e.g. a Support Druid will have different averages compared to a Condi Druid.
+
+
Individual archetypes are denoted by the icon to the left of the profession icon.
+
+
FAQ
+
How do I get GW2 API Key?
+
+
+ Go to ArenaNet Account Applications and authenticate
+ Click the "New Key" button
+ Name your new API key. The name must include the phrase "GW2RAIDAR" in it
+ GW2 Raidar only requires "account" permission
+ Click the "Create API Key" button
+ Your API key will now show; copy it, and paste it into the GW2 Raidar Register form
+
+
+
It says my Account is already registered to another user
+
This means that an API key associated with your account has been used already by another GW2 Raidar user to link your GW2 account. You will need to remove the API key in question (shown in the error message) from your GW2 Account, and possibly create a new API key, in order to prove your ownership of that GW2 account and register your GW2 Raidar account.
+
+
What combat logs does GW2 Raider Support?
+
Combat logs generated by arcdps (both uncompressed and compressed). To enable logging in ARCDPS:
+
+ Press ALT + SHIFT + T, this will bring up the ARC settings window
+ Under the 'Config' section ensure 'SAVE EVTC LOGS ON ENCOUNTERS' is ticked
+ We recommend also ticking 'USE NPC NAME IN EVTC PATH' for easier tracking and 'COMPRESS EVTC WITH PS (WIN 10)' to reduce the size of your logs. Note that compression requires Windows 10
+ Logs are stored by default after each raid boss kill / attempt under 'My Documents/Guild Wars 2/addons/arcdps/arcdps.cbtlogs'
+
+
+
Can I make my info private?
+
You can change your privacy settings in your Account tab. There are three options to choose from:
+
+ Private : Display your account and character names to no-one but yourself
+ Squad : Display your account and character names only to participants in your specific encounter
+ Public : Show your account and character names to everyone
+
+
Privacy options will apply to all accounts and characters linked to your GW2R account.
+
+
What encounters are taken into account for averages?
+
Only encounters marked as successful runs will be included in average statistics. Averages are also isolated by different balance patches (Eras).
diff --git a/raidar/templates/raidar/info_releasenotes.html b/raidar/templates/raidar/info_releasenotes.html
new file mode 100644
index 00000000..e3a3594c
--- /dev/null
+++ b/raidar/templates/raidar/info_releasenotes.html
@@ -0,0 +1,108 @@
+
Release Notes
+
+ Version
+ [[data.version.id]]
+ released on
+ [[formatDate(data.version.timestamp)]]
+
+
+ Added code in preparation for detection of Raid Challenge Mode instances
+ Changed response status code to 4xx for erroneous API upload requests
+
+
Version 1.0.0
+
This major release marks a massive milestone for GW2Raidar. Massive thanks to the community for your support, patience and feedback!
+
+ Added performance graphs to profile page. Clicking on a number in the table will now display a graph showing historical performance vs global metrics for that encounter / archetype combination
+ Added global reporting page. Global reporting will allow any user of the website to view global metrics of all encounters.
+ Added category filter and tag search to encounter list. Encounters page will now display horizontal scroll bar if table does not fit on screen.
+ Added damage absorbed by barrier to combat stats table. Any logs uploaded prior to this release will need to be uploaded again for this feature.
+ Added Regeneration to boon tracking table. Any logs uploaded prior to this release will need to be uploaded again for this feature.
+ Added API endpoint to allow uploading of files directly to the server. Details below:
+
+
+ Added Boon Output tracking output to encounters. Any logs uploaded prior to this release will need to be uploaded again for this feature. Intensity will show average numbers of stacks provided while duration will show average uptime provided for example:
+
+ 75 might on the boon output table indicates and average of 75 stacks were given to everyone by that player during the fight. In a party of 5, that would be 75 / 5 which equals 15 stacks of might uptime for 5 players.
+ 500% alacrity on the boon output table indicates an average of 500% alacrity uptime was provided by that player to the rest of the party. In a party of 5, that would be 500 / 5 which equals 100% alacrity uptime for 5 players.
+
+
+ Re-enabled log archiving. Logs can be redownloaded by clicking on the filename in the top right corner of the encounter page. Privacy options will disable this feature if any player in the squad is deemed private to the user.
+ Many minor fixes to logs not being processed. Most logs impacted have been fed back through for processing.
+ Fixed a server crash.
+ If you love this site and can't live without it, consider a small donation to help support the running costs and invest in better infrastructure for more features!
+
+
Version 0.9.7
+
+ Added game build check for compatible ARC versions. GW2Raidar will now reject logs using game builds where ARC is not functioning properly (latest only).
+ Added Fractal CM support for Nightmare and Shattered Observatory
+ Added basic functionality to categorise raid encounter in preparation for website statistics reporting.
+ Added basic functionality to add custom user tags to encounters. Tags will be editable by all participants.
+
+
Version 0.9.6
+
+ Added more robust success detection. Applies to logs uploaded using ARC version 20170905 or higher
+ Updated 'classic' Xera success detection to minimise occurence of false successes.
+ Added Path of Fire Era. PoF Era will apply to all encounters starting from 22nd September 9AM GMT -7
+
+
Version 0.9.5
+
+ Added privacy options for GW2R Accounts. You can now select between one of the following options:
+
+ Private : Display your account and character names to no-one but yourself
+ Squad : Display your account and character names only to participants in your specific encounter
+ Public : Show your account and character names to everyone
+
+ Privacy options will apply to all accounts and characters linked to your GW2R account.
+
+
Version 0.9.4
+
+ Added basic Kitty Golem log support.
+ Added additional aggregation groups (Raids, Golems)
+ Tweaked log processor to make it more robust.
+ Modified Deimos success detector.
+ Fixed tiny Deimos Phase 2 bars.
+ Removed some less than desirable words from URL wordlist.
+ Fixed a server crash.
+
+
Version 0.9.3
+
+ Added support for non-English GW2 clients
+ From now on, GW2 API key used to authenticate accounts needs to have "gw2raidar" in its name
+ Added support for new ARC Version 20170905
+ Minimum ARC version relaxed to 20170419. Any logs prior to this date will be rejected.
+
+
Version 0.9.2
+
+ Added support for Retaliation uptime. (Any logs uploaded prior to this release will need to be uploaded again for Retaliation to appear.)
+ Better error handling
+
+
Version 0.9.1
+
+ Added multiple processor support
+ Minimum ARC version updated to 20170808. Any logs prior to this date will be rejected
+ Logs for most recent encounters will always be processed first
+
+
Version 0.9.0
+
+
+ Initial Release of GW2Raidar \o/
+
+
diff --git a/raidar/templates/raidar/intro.html b/raidar/templates/raidar/intro.html
new file mode 100644
index 00000000..20cea030
--- /dev/null
+++ b/raidar/templates/raidar/intro.html
@@ -0,0 +1,74 @@
+{% load staticfiles %}
+
What is is GW2 Raidar?
+
+
With the advent and increased usage of DPS meters in Guild Wars 2 Raid scene, there have been a number of different parsers released to analyse, in detail, combat statistics and logs for post review.
+
+
While being able to assist in post encounter analysis is great, current lack one thing, context. GW2 Raidar’s approach to log parsing is slightly different. By retaining high level data about uploaded encounters, GW2 Raidar will allow you compare your individual and squad performance against everyone else’s as an average which will allow you to further analyse your post fight logs.
+
+
With GW2 Raidar you can:
+
+
+ See at a top level your performance and your squad’s performance at a glance
+ See how your and your squads metrics compare to current averages
+ See what the top group metrics and what professions are most popular for each encounter
+ Upload 1 log per encounter and have everyone in the squad access the encounter automatically via their GW2 Raidar account
+ Link multiple Guild Wars 2 accounts to a single GW2 Raidar account for a consolidated single view across all your raid characters
+ See your personal raid statistics as a whole
+
+
+
Getting Started
+
+
Getting started is easy. Simply create a new account on the website. You will need to provide in addition to your desired login credentials, your Guild Wars 2 API Key to confirm your ownership of a Guild Wars 2 Account.
+
+
GW2 Raidar will automatically get your Guild Wars 2 account name and any already uploaded encounters that feature your Guild Wars 2 account will show up straight away in your encounters page.
+
+
Uploading Logs
+
+
To upload your logs, simply drag and drop your arcdps log files into the browser window. GW2 Raidar supports both uncompressed (.evtc
) and compressed (.evtc.zip
) logs. Your logs should appear in the Encounters page after they have been processed. You can access each encounters' data by clicking on the desired row.
+
+
THE NUMBERS MASON! WHAT DO THEY MEAN?
+
+
On each Encounter page, you’ll be shown a few different sections of statistics as per below. For all statistics (with the exception of Party stats), the following colour codes apply:
+
+
+ Red to yellow to green: Visually compares your figure with global average. Red = Worse than average, Yellow = On par, Green = Better than average
+ Purple: Visually represent the current average
+
+
+
Squad
+
+
+
Shows total squad values. The first number denotes your squad’s totals with the second number denoting the current global average
+
+
Party
+
+
+
Allows you compare individual party information to see performance of each sub group. These have no averages.
+
+
Individual
+
+
+
Shows individual values. The first number denotes individual values with the second number denoting the current global average. All averages are based on the detected archetype e.g. a Support Druid will have different averages compared to a Condi Druid.
+
+
Individual archetypes are denoted by the icon to the left of the profession icon.
+
+
FAQ
+
How do I get GW2 API Key?
+
+
+ Go to ArenaNet Account Applications and authenticate
+ Click the "New Key" button
+ Name your new API key sensibly (e.g. "GW2Raidar")
+ GW2 Raidar only requires "account" permission
+ Click the "Create API Key" button
+ Your API key will now show; copy it, and paste it into the GW2 Raidar Register form
+
+
+
It says my Account is already registered to another user
+
This means that an API key associated with your account has been used already by another GW2 Raidar user to link your GW2 account. You will need to remove the API key in question (shown in the error message) from your GW2 Account, and possibly create a new API key, in order to prove your ownership of that GW2 account and register your GW2 Raidar account.
+
+
I can’t see an encounter someone else linked me
+
If your linked account was not in the raid squad for an encounter someone else uploaded then you will not be able to see the encounter view.
+
+
What combat logs does GW2 Raider Support?
+
Combat logs generated by arcdps (both uncompressed and compressed). Supports logs from arcdps Version May 21 2017.
diff --git a/raidar/templates/raidar/navbar.html b/raidar/templates/raidar/navbar.html
new file mode 100644
index 00000000..e63c308f
--- /dev/null
+++ b/raidar/templates/raidar/navbar.html
@@ -0,0 +1,38 @@
+
+
+
+
diff --git a/raidar/templates/raidar/profile.html b/raidar/templates/raidar/profile.html
new file mode 100644
index 00000000..2f0f013a
--- /dev/null
+++ b/raidar/templates/raidar/profile.html
@@ -0,0 +1,145 @@
+{% load staticfiles %}
+[[#with profile]]
+
+
+
Profile: [[username]]
+
+ Member since [[formatDate(joined_at)]]
+
+
+
Played through
+ [[page.era.profile.count]]
+
encounters in
+
[[page.era.name]]
+
+
[[page.era.name]] Era
+
Started at: [[formatDate(page.era.started_at)]]
+
[[page.era.description]]
+
+
era
+
+
+
+
+ [[#each eras]]
+ [[name]]
+ [[/each]]
+
+
+
+
+
+ [[#with page.era.profile]]
+
+
+ [[#each keysWithAllLast(encounter, data.areas)]]
+ [[#with {encounterId: .}]]
+ [[#with encounter[encounterId].archetype.All.profession.All.elite.All]]
+
+
+ [[encounterId.match(/^All \w+ bosses$/) ? encounterId : data.areas[encounterId]]]
+ ([[count]])
+
+ [[/with]]
+ [[/with]]
+ [[/each]]
+
+
+
+
+ [[#if encounter[page.area]]]
+
+
+
Live [[
+ (100
+ - encounter[page.area].archetype.All.profession.All.elite.All.avg_down_percentage
+ - encounter[page.area].archetype.All.profession.All.elite.All.avg_dead_percentage
+ ).toPrecision(3)]]%
+
Down [[encounter[page.area].archetype.All.profession.All.elite.All.avg_down_percentage.toPrecision(3)]]%
+
Dead [[encounter[page.area].archetype.All.profession.All.elite.All.avg_dead_percentage.toPrecision(3)]]%
+
+
+
Support [[encounter[page.area].archetype[5] ? (100 * encounter[page.area].archetype[5].profession.All.elite.All.count / encounter[page.area].archetype.All.profession.All.elite.All.count).toPrecision(3) : 0]]%
+
Power [[encounter[page.area].archetype[1] ? (100 * encounter[page.area].archetype[1].profession.All.elite.All.count / encounter[page.area].archetype.All.profession.All.elite.All.count).toPrecision(3) : 0]]%
+
Condi [[encounter[page.area].archetype[2] ? (100 * encounter[page.area].archetype[2].profession.All.elite.All.count / encounter[page.area].archetype.All.profession.All.elite.All.count).toPrecision(3) : 0]]%
+
+
+
+
+ [[#each keysWithAllLast(encounter[page.area].archetype, {1: 2, 2: 3, 5: 1})]]
+ [[#with {archetypeId: ., archetype: encounter[page.area].archetype[.]}]]
+
+ [[#if archetypeId !== 'All']]
+
+ [[/if]]
+ [[archetypeId === 'All' ? 'All' : data.archetypes[archetypeId]]]
+ Archetypes on
+ [[page.area.match(/^All \w+ bosses$/) ? page.area : data.areas[page.area]]]
+
+
+
+
+ Profession
+ Encounters
+ Avg DPS
+ Max DPS
+ Avg Boss DPS
+ Max Boss DPS
+ Down
+ Dead
+
+
+
+ [[#each keysWithAllLast(archetype.profession)]]
+ [[#with {professionId: ., profession: archetype.profession[.]}]]
+ [[#each keysWithAllLast(profession.elite)]]
+ [[#with {eliteId: ., elite: profession.elite[.]}]]
+ [[#with elite]]
+
+
+ [[#if professionId !== 'All']]
+
+ [[/if]]
+ [[professionId === 'All' ? 'All' : data.specialisations[professionId][eliteId]]]
+
+
+ [[.count]]
+
+
+ [[.avg_dps !== undefined ? Math.round(.avg_dps) : '']]
+
+
+ [[.max_dps !== undefined ? Math.round(.max_dps) : '']]
+
+
+ [[.avg_dps_boss !== undefined ? Math.round(.avg_dps_boss) : '']]
+
+
+ [[.max_dps_boss !== undefined ? Math.round(.max_dps_boss) : '']]
+
+
+ [[.avg_down_percentage !== undefined ? .avg_down_percentage.toPrecision(3) + '%' : '']]
+
+
+ [[.avg_dead_percentage !== undefined ? .avg_dead_percentage.toPrecision(3) + '%' : '']]
+
+
+ [[/with]]
+ [[/with]]
+ [[/each]]
+ [[/with]]
+ [[/each]]
+
+
+ [[/with]]
+ [[/each]]
+ [[/if]]
+ [[/with]]
+[[/with]]
diff --git a/raidar/templates/raidar/thank-you.html b/raidar/templates/raidar/thank-you.html
new file mode 100644
index 00000000..c8cc1023
--- /dev/null
+++ b/raidar/templates/raidar/thank-you.html
@@ -0,0 +1,6 @@
+
Thank you!
+
Thank you so much for your donation!! We work hard to try and bring something valuable to the Guild Wars 2 community and your donation will help us continually do so. Not only will it help towards the monthly running costs, but will also allow us to look into investing into better infrastructure which will result in a more feature rich website for the entire community.
+
Not only that, but it will keep this website ad free and free from subscriptions for everyone to use.
+
if you have any questions, suggestions, feedback or to become a regular donor, feel free to contact us
+
Sincerely,
+
Merforga and the rest of the GW2R team
diff --git a/raidar/templates/raidar/uploads.html b/raidar/templates/raidar/uploads.html
new file mode 100644
index 00000000..cf66d6e9
--- /dev/null
+++ b/raidar/templates/raidar/uploads.html
@@ -0,0 +1,55 @@
+
+
+
+
+ File
+
+
+ Uploader
+
+
+ Status
+
+
+
+
+ [[#each upload]]
+
+
+ [[name]]
+
+
+ [[uploaded_by]]
+
+
+ [[#if success]]
+ Success
+ [[elseif success === false]]
+ [[error || "Error"]]
+ [[elseif progress]]
+ [[#if progress < 100]]
+ Uploading [[progress]]%
+ [[else]]
+ Analysing
+ [[/if]]
+ [[else]]
+ Queued
+ [[/if]]
+
+
+ [[/each]]
+
+
+
+
+ To upload your logs, simply drag and drop them anywhere into GW2 Raidar.
+ GW2 Raidar supports both .evtc
and .evtc.zip
formats
+ from ARCDPS. While they're being uploaded, you can continue to browse around
+ the website. Click on any log file marked green to view the results.
+
+
+ Processing may take a few minutes, however once a log is in a status of "Analysing", it will be processed even if you leave the website.
+
+
+ Note that refreshing or closing the page will cancel any pending uploads.
+
diff --git a/raidar/urls.py b/raidar/urls.py
index dd172474..d1f21fd6 100644
--- a/raidar/urls.py
+++ b/raidar/urls.py
@@ -1,12 +1,39 @@
-from django.conf.urls import url
+from django.conf import settings
+from django.conf.urls import url, include
+from django.contrib.auth import views as auth_views
+import importlib
from . import views
urlpatterns = [
- url(r'initial', views.initial, name = "initial"),
- url(r'login', views.login, name = "login"),
- url(r'logout', views.logout, name = "logout"),
- url(r'register', views.register, name = "register"),
- url(r'upload', views.upload, name = "upload"),
- url(r'^$', views.index, name = "index"),
+ url(r'^(?P
encounters|profile|uploads|account|register|login|index|reset_pw|thank-you|info-(?:help|releasenotes|contact|about))(?:/(?P\w+))?$', views.named, name = "named"),
+ url(r'^initial.json$', views.initial, name = "initial"),
+ url(r'^login.json$', views.login, name = "login"),
+ url(r'^logout.json$', views.logout, name = "logout"),
+ url(r'^register.json$', views.register, name = "register"),
+ url(r'^reset_pw.json$', views.reset_pw, name = "reset_pw"),
+ url(r'^upload.json$', views.upload, name = "upload"),
+ url(r'^api/upload.json$', views.api_upload, name = "api_upload"),
+ url(r'^privacy.json$', views.privacy, name = "privacy"),
+ url(r'^profile_graph.json$', views.profile_graph, name = "profile_graph"),
+ url(r'^set_tags_cat.json$', views.set_tags_cat, name = "set_tags_cat"),
+ url(r'^contact.json$', views.contact, name = "contact"),
+ url(r'^poll.json$', views.poll, name = "poll"),
+ url(r'^change_email.json$', views.change_email, name = "change_email"),
+ url(r'^change_password.json$', views.change_password, name = "change_password"),
+ url(r'^add_api_key.json$', views.add_api_key, name = "add_api_key"),
+ url(r'^encounter/(?P\w+)(?P\.json)?$', views.encounter, name = "encounter"),
+ url(r'^profile.json$', views.profile, name = "profile"),
+ url(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
+ auth_views.password_reset_confirm, name='password_reset_confirm'),
+ url(r'^reset/done/$', auth_views.password_reset_complete, name='password_reset_complete'),
+ url(r'^download/(?P\w+)?$', views.download, name="download"),
+ url(r'^$', views.index, name = "index"),
+ url(r'^global_stats(?:/(?P[0-9]+))?(?:/area-(?P[0-9]+))?(?P\.json)?$', views.global_stats, name = "global_stats"),
]
+
+if settings.DEBUG and importlib.util.find_spec('debug_toolbar'):
+ import debug_toolbar
+ urlpatterns = [
+ url(r'^__debug__/', include(debug_toolbar.urls)),
+ ] + urlpatterns
diff --git a/raidar/views.py b/raidar/views.py
index a7bd1aab..d2093713 100644
--- a/raidar/views.py
+++ b/raidar/views.py
@@ -1,44 +1,72 @@
-from json import dumps as json_dumps
-from django.http import JsonResponse
-from django.shortcuts import render
-from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
-from django.middleware.csrf import get_token
+from .models import *
+from analyser.analyser import Analyser, Group, Archetype, EvtcAnalysisException
+from analyser.bosses import BOSSES
+from django.conf import settings
+from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout, update_session_auth_hash
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.forms import PasswordChangeForm, PasswordResetForm
from django.contrib.auth.models import User
+from django.contrib.auth.tokens import default_token_generator
+from django.core import serializers
+from django.core.mail import EmailMessage
+from django.views.decorators.csrf import csrf_exempt
+from smtplib import SMTPException
from django.db.utils import IntegrityError
+from django.http import JsonResponse, HttpResponse, Http404
+from django.middleware.csrf import get_token
+from django.shortcuts import render
+from django.utils import timezone
+from django.utils.http import urlsafe_base64_decode
+from django.views.decorators.cache import never_cache
+from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables
from django.views.decorators.http import require_GET, require_POST
-from django.contrib.auth.decorators import login_required
-from evtcparser.parser import Encounter as EvtcEncounter
-from analyser.analyser import Analyser
+from gw2api.gw2api import GW2API, GW2APIException
+from itertools import groupby
+from json import dumps as json_dumps
+from os import makedirs, sep as dirsep
+from os.path import join as path_join, isfile, dirname
+import pytz
from datetime import datetime
-from django.utils import timezone
-from django.core import serializers
-from re import match
-from .models import *
+from re import match, sub
+from time import time
+import logging
+import numpy as np
+import base64
+
+logger = logging.getLogger(__name__)
+def _safe_get(f, default=None):
+ try:
+ return f()
+ except (KeyError, TypeError):
+ return default
-def _error(msg, **kwargs):
- kwargs['error'] = msg
- return JsonResponse(kwargs)
+def _error(msg, status=200, **kwargs):
+ kwargs['error'] = str(msg)
+ return JsonResponse(kwargs, status=status)
def _userprops(request):
- if request.user:
+ accounts = request.user.accounts.all() if request.user.is_authenticated else []
return {
'username': request.user.username,
- 'is_staff': request.user.is_staff
+ 'is_staff': request.user.is_staff,
+ 'accounts': [{
+ "name": account.name,
+ "api_key": account.api_key[:8] +
+ sub(r"[0-9a-fA-F]", "X", account.api_key[8:-12]) +
+ account.api_key[-12:]
+ if account.api_key != "" else "",
+ }
+ for account in accounts],
}
- else:
- return {}
+
def _encounter_data(request):
- encounters = Encounter.objects.filter(characters__account__user=request.user)
- return [{
- 'id': encounter.id,
- 'area': encounter.area.name,
- 'started_at': int(encounter.started_at.strftime('%s')),
- } for encounter in encounters]
+ participations = Participation.objects.filter(character__account__user=request.user).select_related('encounter', 'character', 'character__account')
+ return [participation.data() for participation in participations]
def _login_successful(request, user):
auth_login(request, user)
@@ -46,27 +74,307 @@ def _login_successful(request, user):
userprops = _userprops(request)
userprops['csrftoken'] = csrftoken
userprops['encounters'] = _encounter_data(request)
+ userprops['privacy'] = request.user.user_profile.privacy
return JsonResponse(userprops)
-@require_GET
-def index(request):
+
+def _html_response(request, page, data={}):
+ response = _userprops(request)
+ response.update(data)
+ try:
+ response['ga_property_id'] = settings.GA_PROPERTY_ID
+ except:
+ # No Google Analytics, it's fine
+ pass
+ response['archetypes'] = {k: v for k, v in Participation.ARCHETYPE_CHOICES}
+ response['areas'] = {area.id: area.name for area in Area.objects.all()}
+ response['specialisations'] = {p: {e: n for (pp, e), n in Character.SPECIALISATIONS.items() if pp == p} for p, _ in Character.PROFESSION_CHOICES}
+ response['categories'] = {category.id: category.name for category in Category.objects.all()}
+ response['page'] = page
+ response['debug'] = settings.DEBUG
+ response['version'] = settings.VERSION
+ if request.user.is_authenticated:
+ response['privacy'] = request.user.user_profile.privacy
+ if request.user.is_authenticated:
+ try:
+ last_notification = request.user.notifications.latest('id')
+ response['last_notification_id'] = last_notification.id
+ except Notification.DoesNotExist:
+ # it's okay
+ pass
return render(request, template_name='raidar/index.html', context={
- 'userprops': json_dumps(_userprops(request))
+ 'userprops': json_dumps(response),
})
+@require_GET
+def download(request, url_id=None):
+ if not hasattr(settings, 'UPLOAD_DIR'):
+ return Http404("Not allowed")
+
+ encounter = Encounter.objects.get(url_id=url_id)
+ own_account_names = [account.name for account in Account.objects.filter(
+ characters__participations__encounter_id=encounter.id,
+ user=request.user)]
+ dump = encounter.val
+ members = [{ "name": name, **value } for name, value in dump['Category']['status']['Player'].items() if 'account' in value]
+
+ encounter_showable = True
+ for member in members:
+ is_self = member['account'] in own_account_names
+
+ user_profile = UserProfile.objects.filter(user__accounts__name=member['account'])
+ if user_profile:
+ privacy = user_profile[0].privacy
+ if not is_self and (privacy == UserProfile.PRIVATE or (privacy == UserProfile.SQUAD and not own_account_names)):
+ encounter_showable = False
+
+ path = encounter.diskname()
+ if isfile(path) and (encounter_showable or request.user.is_staff):
+ response = HttpResponse(open(path, 'rb'), content_type='application/vnd.ms-excel')
+ response['Content-Disposition'] = 'attachment; filename="%s"' % encounter.filename
+ return response
+ else:
+ raise Http404("Not allowed")
+
+
+@require_GET
+def index(request, page={ 'name': '' }):
+ return _html_response(request, page)
+
+
+@require_GET
+def profile(request):
+ if not request.user.is_authenticated:
+ return _error("Not authenticated")
+
+ user = request.user
+ queryset = EraUserStore.objects.filter(user=user).select_related('era')
+ try:
+ eras = [{
+ 'id': era_user_store.era_id,
+ 'name': era_user_store.era.name,
+ 'started_at': era_user_store.era.started_at,
+ 'description': era_user_store.era.description,
+ 'profile': era_user_store.val,
+ } for era_user_store in queryset]
+ except EraUserStore.DoesNotExist:
+ eras = []
+
+ profile = {
+ 'username': user.username,
+ 'joined_at': (user.date_joined - datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC)).total_seconds(),
+ 'eras': eras,
+ }
+
+ result = {
+ "profile": profile
+ }
+ return JsonResponse(result)
+
+@require_GET
+def global_stats(request, era_id=None, area_id=None, json=None):
+ if not json:
+ return _html_response(request, {
+ "name": "global_stats",
+ "era_id": era_id,
+ "area_id": area_id
+ })
+ try:
+ era_query = Era.objects.all()
+ eras = [{
+ 'name': era.name,
+ 'id': era.id,
+ 'started_at': era.started_at,
+ 'description': era.description
+ } for era in era_query]
+ except Era.DoesNotExist:
+ eras = []
+
+ try:
+ area_query = Area.objects.filter(era_area_stores__isnull = False).distinct()
+ areas = [{
+ 'name': area.name,
+ 'id': area.id,
+ } for area in area_query]
+ except Area.DoesNotExist:
+ areas = []
+
+ try:
+ if era_id is None:
+ era_id = eras[0]['id']
+ era = Era.objects.get(id=era_id)
+ if area_id is None:
+ raw_data = era.val
+ else:
+ area = Area.objects.get(id=area_id)
+ raw_data = EraAreaStore.objects.get(era=era, area=area).val
+ stats = raw_data['All']
+
+ #reduce size of json for global stats view
+ builds = [stats['build'][prof][elite][arch]
+ for prof in stats['build']
+ for elite in stats['build'][prof]
+ for arch in stats['build'][prof][elite]]
+
+ builds.append(stats['group'])
+ builds.append(stats['individual'])
+
+ for build in list(builds):
+ if 'buffs' in build:
+ del build['buffs']
+ if 'count' not in build or build['count'] < 10:
+ for key in list(build.keys()):
+ del(build[key])
+
+ if 'buffs_out' in build:
+ for buff in list(filter(lambda a: a.startswith('max_'), build['buffs_out'].keys())):
+ if build['buffs_out'][buff] <= 0.01:
+ buffname = buff[4:]
+ for key in list(filter(lambda a: a.split('_', 1)[1] == buffname,
+ build['buffs_out'].keys())):
+ del(build['buffs_out'][key])
+
+ except (Era.DoesNotExist, Area.DoesNotExist, EraAreaStore.DoesNotExist, KeyError):
+ stats = {}
+
+ result = {'global_stats': {
+ 'eras': eras,
+ 'areas': areas,
+ 'stats': stats
+ }}
+ return JsonResponse(result)
+
+
+@require_GET
+def encounter(request, url_id=None, json=None):
+ try:
+ encounter = Encounter.objects.select_related('area', 'uploaded_by').get(url_id=url_id)
+ except Encounter.DoesNotExist:
+ if json:
+ return _error("Encounter does not exist")
+ else:
+ raise Http404("Encounter does not exist")
+ own_account_names = [account.name for account in Account.objects.filter(
+ characters__participations__encounter_id=encounter.id,
+ user=request.user)] if request.user.is_authenticated else []
+
+ dump = encounter.val
+ members = [{ "name": name, **value } for name, value in dump['Category']['status']['Player'].items() if 'account' in value]
+
+ try:
+ area_stats = EraAreaStore.objects.get(era=encounter.era, area=encounter.area).val
+ except EraAreaStore.DoesNotExist:
+ area_stats = None
+ phases = _safe_get(lambda: dump['Category']['encounter']['phase_order'] + ['All'], list(dump['Category']['combat']['Phase'].keys()))
+ partyfunc = lambda member: member['party']
+ namefunc = lambda member: member['name']
+ parties = { party: {
+ "members": sorted(members, key=namefunc),
+ "phases": {
+ phase: {
+ "actual": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['damage']['To']['*All']),
+ "actual_boss": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['damage']['To']['*Boss']),
+ "received": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['damage']['From']['*All']),
+ "shielded": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['shielded']['From']['*All']),
+ "buffs": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['buffs']['From']['*All']),
+ "buffs_out": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['buffs']['To']['*All']),
+ "events": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['events']),
+ "mechanics": _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup'][str(party)]['Metrics']['mechanics']),
+ } for phase in phases
+ }
+ } for party, members in groupby(sorted(members, key=partyfunc), partyfunc) }
+ private = False
+
+ encounter_showable = True
+ for party_no, party in parties.items():
+ for member in party['members']:
+ if member['account'] in own_account_names:
+ member['self'] = True
+ member['phases'] = {
+ phase: {
+ 'actual': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['damage']['To']['*All']),
+ 'actual_boss': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['damage']['To']['*Boss']),
+ 'received': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['damage']['From']['*All']),
+ 'shielded': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['shielded']['From']['*All']),
+ 'buffs': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['buffs']['From']['*All']),
+ 'buffs_out': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['buffs']['To']['*All']),
+ 'events': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['events']),
+ 'mechanics': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Player'][member['name']]['Metrics']['mechanics']),
+ 'archetype': _safe_get(lambda: area_stats[phase]['build'][str(member['profession'])][str(member['elite'])][str(member['archetype'])]),
+ } for phase in phases
+ }
+
+ user_profile = UserProfile.objects.filter(user__accounts__name=member['account'])
+ if user_profile:
+ privacy = user_profile[0].privacy
+ if 'self' not in member and (privacy == UserProfile.PRIVATE or (privacy == UserProfile.SQUAD and not own_account_names)):
+ member['name'] = ''
+ member['account'] = ''
+ private = True
+ encounter_showable = False
+
+ data = {
+ "encounter": {
+ "evtc_version": _safe_get(lambda: dump['Category']['encounter']['evtc_version']),
+ "id": encounter.id,
+ "url_id": encounter.url_id,
+ "name": encounter.area.name,
+ "filename": encounter.filename,
+ "uploaded_at": encounter.uploaded_at,
+ "uploaded_by": encounter.uploaded_by.username,
+ "started_at": encounter.started_at,
+ "duration": encounter.duration,
+ "success": encounter.success,
+ "tags": encounter.tagstring,
+ "category": encounter.category_id,
+ "phase_order": phases,
+ "participated": own_account_names != [],
+ "boss_metrics": [metric.__dict__ for metric in BOSSES[encounter.area_id].metrics],
+ "phases": {
+ phase: {
+ 'duration': encounter.duration if phase == "All" else _safe_get(lambda: dump['Category']['encounter']['Phase'][phase]['duration']),
+ 'group': _safe_get(lambda: area_stats[phase]['group']),
+ 'individual': _safe_get(lambda: area_stats[phase]['individual']),
+ 'actual': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['damage']['To']['*All']),
+ 'actual_boss': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['damage']['To']['*Boss']),
+ 'received': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['damage']['From']['*All']),
+ 'shielded': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['shielded']['From']['*All']),
+ 'buffs': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['buffs']['From']['*All']),
+ 'buffs_out': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['buffs']['To']['*All']),
+ 'events': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['events']),
+ 'mechanics': _safe_get(lambda: dump['Category']['combat']['Phase'][phase]['Subgroup']['*All']['Metrics']['mechanics']),
+ } for phase in phases
+ },
+ "parties": parties,
+ }
+ }
+ if encounter_showable or request.user.is_staff:
+ if encounter.gdrive_url:
+ data['encounter']['evtc_url'] = encounter.gdrive_url;
+ # XXX relic TODO remove once we fully cross to GDrive?
+ if hasattr(settings, 'UPLOAD_DIR'):
+ path = encounter.diskname()
+ if isfile(path):
+ data['encounter']['downloadable'] = True
+
+ if json:
+ return JsonResponse(data)
+ else:
+ return _html_response(request, { "name": "encounter", "no": encounter.url_id }, data)
+
@require_GET
def initial(request):
response = _userprops(request)
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
response['encounters'] = _encounter_data(request)
return JsonResponse(response)
-@require_POST
-def login(request):
+@sensitive_variables('password')
+def _perform_login(request):
username = request.POST.get('username')
password = request.POST.get('password')
# stayloggedin = request.GET.get('stayloggedin')
@@ -75,29 +383,92 @@ def login(request):
# else:
# request.session.set_expiry(0)
- user = authenticate(username=username, password=password)
+ return authenticate(username=username, password=password)
+
+
+@require_POST
+@sensitive_post_parameters('password')
+def login(request):
+ if request.method == 'GET':
+ return index(request, page={ 'name': 'login' })
+
+ user = _perform_login(request)
if user is not None and user.is_active:
return _login_successful(request, user)
else:
return _error('Could not log in')
-
@require_POST
-def register(request):
- username = request.POST.get('username')
- password = request.POST.get('password')
+@never_cache
+def reset_pw(request):
email = request.POST.get('email')
+ form = PasswordResetForm(request.POST)
+ if form.is_valid():
+ opts = {
+ 'use_https': request.is_secure(),
+ 'email_template_name': 'registration/password_reset_email.html',
+ 'subject_template_name': 'registration/password_reset_subject.txt',
+ 'request': request,
+ }
+ form.save(**opts)
+ return JsonResponse({});
+
+
+@sensitive_post_parameters('password')
+@sensitive_variables('password')
+def register(request):
+ if request.method == 'GET':
+ return index(request, page={ 'name': 'register' })
+
+ username = request.POST.get('username').strip()
+ password = request.POST.get('password').strip()
+ email = request.POST.get('email').strip()
+ api_key = request.POST.get('api_key').strip()
+ gw2api = GW2API(api_key)
+
+ try:
+ token_info = gw2api.query("/tokeninfo")
+ if 'gw2raidar' not in token_info['name'].lower():
+ return _error("Your api key must be named 'gw2raidar'.")
+ gw2_account = gw2api.query("/account")
+ except GW2APIException as e:
+ return _error(e)
+
+ account_name = gw2_account['name']
+ account, _ = Account.objects.get_or_create(name=account_name)
+
+ if account.user and account.user != request.user:
+ # Registered to another account
+ old_gw2api = GW2API(account.api_key)
+ try:
+ gw2_account = old_gw2api.query("/account")
+ # Old key is still valid, ask user to invalidate it
+ try:
+ old_api_key_info = old_gw2api.query("/tokeninfo")
+ key_id = "named '%s'" % old_api_key_info['name']
+ except GW2APIException as e:
+ key_id = "ending in '%s'" % api_key[-4:]
+ new_key = "" if account.api_key != api_key else " and generate a new key"
+
+ return _error("This GW2 account is registered to another user. To prove it is yours, please invalidate the key %s%s." % (key_id, new_key))
+ except GW2APIException as e:
+ # Old key is invalid, reassign OK
+ pass
try:
user = User.objects.create_user(username, email, password)
except IntegrityError:
return _error('Such a user already exists')
- if user:
- return _login_successful(request, user)
- else:
+ if not user:
return _error('Could not register user')
+ account.user = user
+ account.api_key = api_key
+ account.save()
+
+ return _login_successful(request, user)
+
@login_required
@require_POST
@@ -107,65 +478,237 @@ def logout(request):
return JsonResponse({})
+def _perform_upload(request):
+ if (len(request.FILES) != 1):
+ return ("Only single file uploads are allowed", None)
+
+ filename = next(iter(request.FILES))
+ if 'file' in request.FILES:
+ file = request.FILES['file']
+ else:
+ return ("Missing file attachment named `file`", None)
+ filename = file.name
+ uploaded_at = time()
+
+ upload, _ = Upload.objects.update_or_create(
+ filename=filename, uploaded_by=request.user,
+ defaults={ "uploaded_at": time() })
+
+ diskname = upload.diskname()
+ makedirs(dirname(diskname), exist_ok=True)
+ with open(diskname, 'wb') as diskfile:
+ while True:
+ buf = file.read(16384)
+ if len(buf) == 0:
+ break
+ diskfile.write(buf)
+ return (filename, upload)
+
+
@login_required
@require_POST
def upload(request):
- user_account_names = [account.name for account in request.user.accounts.all()]
+ filename, upload = _perform_upload(request)
- result = {}
- # TODO this should really only be one file
- # so make adjustments to find out its name and only provide one result
+ return JsonResponse({"filename": filename, "upload_id": upload.id})
- for filename, file in request.FILES.items():
- try:
- started_at = datetime.strptime(filename, '%Y%m%d-%H%M%S.evtc')
- except:
- return _error('Filename not valid')
- started_at = timezone.make_aware(started_at, timezone.utc)
-
- # metrics is a tree with 2 types of nodes:
- # iterables containing key/value tuples
- # or basic values
- # should be easy to convert to json
- evtc_encounter = EvtcEncounter(file)
-
- players = [agent for agent in evtc_encounter.agents if agent.account]
- if not players:
- return _error('No players in encounter')
-
- analyser = Analyser(evtc_encounter)
- metrics = analyser.compute_all_metrics()
- # TODO metrics
-
-
- area = Area.objects.get(id=evtc_encounter.area_id)
- if not area:
- return _error('Unknown area')
-
- # heuristics to see if the encounter is a re-upload:
- # a character can only be in one raid at a time
- # XXX: it is *theoretically* possible for this to be in a race
- # condition, so that the encounter is duplicated and later raises an
- # error. try/catch, if returns multiple then delete all but one?
- encounter, encounter_created = Encounter.objects.get_or_create(
- area=area, started_at=started_at, characters__name=players[0].name)
-
- show = False
- for player in players:
- if player.account in user_account_names:
- show = True
- account, _ = Account.objects.get_or_create(
- name=player.account)
- character, _ = Character.objects.get_or_create(
- name=player.name, account=account, profession=player.prof.value)
- participation, _ = Participation.objects.get_or_create(
- character=character, encounter=encounter)
- if show:
- result[filename] = {
- 'id': encounter.id,
- 'area': encounter.area.name,
- 'started_at': int(started_at.strftime('%s')),
- 'new': encounter_created,
- }
+@csrf_exempt
+@require_POST
+@sensitive_post_parameters('password')
+def api_upload(request):
+ user = _perform_login(request)
+ if not user:
+ return _error('Could not authenticate', status=401)
+ auth_login(request, user)
+ filename, upload = _perform_upload(request)
+ if not upload:
+ return _error(filename, status=400)
+
+ return JsonResponse({"filename": filename, "upload_id": upload.id})
+
+
+@login_required
+@require_POST
+def profile_graph(request):
+ era_id = request.POST['era']
+ area_id = request.POST['area']
+ archetype_id = request.POST['archetype']
+ profession_id = request.POST['profession']
+ elite_id = request.POST['elite']
+ stat = request.POST['stat']
+
+ participations = Participation.objects.select_related('encounter').filter(
+ encounter__era_id=era_id, character__account__user=request.user, encounter__success=True)
+
+ try:
+ if area_id.startswith('All'):
+ store = Era.objects.get(pk=era_id).val[area_id]
+ else:
+ participations = participations.filter(encounter__area_id=area_id)
+ store = EraAreaStore.objects.get(era_id=era_id, area_id=area_id).val
+ except (EraAreaStore.DoesNotExist, Era.DoesNotExist, KeyError):
+ store = {}
+ if archetype_id != 'All':
+ participations = participations.filter(archetype=archetype_id)
+ if profession_id != 'All':
+ participations = participations.filter(character__profession=profession_id)
+ if elite_id != 'All':
+ participations = participations.filter(elite=elite_id)
+
+ try:
+ requested = store['All']['build'][profession_id][elite_id][archetype_id]
+ requested = {
+ 'avg': requested['avg_' + stat],
+ 'per': list(np.frombuffer(base64.b64decode(requested['per_' + stat].encode('utf-8')), dtype=np.float32).astype(float)),
+ }
+ except KeyError:
+ requested = None # XXX fill out in restat
+ MAX_GRAPH_ENCOUNTERS = 50 # XXX move to top or to settings
+ db_data = participations.order_by('-encounter__started_at')[:MAX_GRAPH_ENCOUNTERS].values_list('character__name', 'encounter__started_at', 'encounter__value')
+ data = []
+ times = []
+
+ if stat == 'dps_boss':
+ target = '*Boss'
+ stat = 'dps'
+ else:
+ target = '*All'
+ for name, started_at, json in reversed(db_data):
+ dump = json_loads(json)
+ datum = _safe_get(lambda: dump['Category']['combat']['Phase']['All']['Player'][name]['Metrics']['damage']['To'][target][stat], 0)
+ data.append(datum)
+ times.append(started_at)
+
+ result = {
+ 'globals': requested,
+ 'data': data,
+ 'times': times,
+ }
+ return JsonResponse(result)
+
+
+@require_GET
+def named(request, name, no):
+ return index(request, { 'name': name, 'no': int(no) if type(no) == str else no })
+@login_required
+@require_POST
+def poll(request):
+ notifications = Notification.objects.filter(user=request.user)
+ last_id = request.POST.get('last_id')
+ if last_id:
+ notifications = notifications.filter(id__gt=last_id)
+ result = { "notifications": [notification.val for notification in notifications] }
+ if notifications:
+ result['last_id'] = notifications.last().id
return JsonResponse(result)
+
+@login_required
+@require_POST
+def privacy(request):
+ profile = request.user.user_profile
+ profile.privacy = int(request.POST.get('privacy'))
+ profile.save()
+ return JsonResponse({})
+
+@login_required
+@require_POST
+def set_tags_cat(request):
+ encounter = Encounter.objects.get(pk=int(request.POST.get('id')))
+ participation = encounter.participations.filter(character__account__user=request.user).exists()
+ if not participation:
+ return _error('Not a participant')
+ encounter.tagstring = request.POST.get('tags')
+ encounter.category_id = request.POST.get('category')
+ encounter.save()
+ return JsonResponse({})
+
+@login_required
+@require_POST
+def change_email(request):
+ request.user.email = request.POST.get('email')
+ request.user.save()
+ return JsonResponse({})
+
+@login_required
+@sensitive_post_parameters()
+@sensitive_variables('form')
+@require_POST
+def change_password(request):
+ form = PasswordChangeForm(request.user, request.POST)
+ if form.is_valid():
+ user = form.save()
+ update_session_auth_hash(request, user)
+ return JsonResponse({})
+ else:
+ return _error(' '.join(' '.join(v) for k, v in form.errors.items()))
+
+@require_POST
+def contact(request):
+ subject = request.POST.get('subject')
+ body = request.POST.get('body')
+ if request.user.is_authenticated:
+ name = request.user.username
+ email = request.user.email
+ else:
+ name = request.POST.get('name')
+ email = request.POST.get('email')
+
+ try:
+ headers = {'Reply-To': "%s <%s>" % (name, email)}
+ msg = EmailMessage(
+ settings.EMAIL_SUBJECT_PREFIX + '[contact] ' + subject,
+ body,
+ '"%s" <%s>' % (name, settings.DEFAULT_FROM_EMAIL),
+ [settings.DEFAULT_FROM_EMAIL],
+ reply_to=['%s <%s>' % (name, email)])
+ msg.send(False)
+ except SMTPException as e:
+ return _error(e)
+
+ return JsonResponse({})
+
+
+@login_required
+@require_POST
+def add_api_key(request):
+ api_key = request.POST.get('api_key').strip()
+ gw2api = GW2API(api_key)
+
+ try:
+ token_info = gw2api.query("/tokeninfo")
+ if 'gw2raidar' not in token_info['name'].lower():
+ return _error("Your api key must be named 'gw2raidar'.")
+ gw2_account = gw2api.query("/account")
+ except GW2APIException as e:
+ return _error(e)
+
+ account_name = gw2_account['name']
+ account, _ = Account.objects.get_or_create(name=account_name)
+
+ if account.user and account.user != request.user:
+ # Registered to another account
+ old_gw2api = GW2API(account.api_key)
+ try:
+ gw2_account = old_gw2api.query("/account")
+ # Old key is still valid, ask user to invalidate it
+ try:
+ old_api_key_info = old_gw2api.query("/tokeninfo")
+ key_id = "named '%s'" % old_api_key_info['name']
+ except GW2APIException as e:
+ key_id = "ending in '%s'" % api_key[-4:]
+ new_key = "" if account.api_key != api_key else " and generate a new key"
+
+ return _error("This GW2 account is registered to another user. To prove it is yours, please invalidate the key %s%s." % (key_id, new_key))
+ except GW2APIException as e:
+ # Old key is invalid, reassign OK
+ pass
+
+ account.user = request.user
+ account.api_key = api_key
+ account.save()
+
+ return JsonResponse({
+ 'account_name': account_name,
+ 'encounters': _encounter_data(request)
+ })
diff --git a/raidar/words.txt b/raidar/words.txt
new file mode 100644
index 00000000..d260e2a1
--- /dev/null
+++ b/raidar/words.txt
@@ -0,0 +1,10776 @@
+a
+abandon
+abandoned
+abandoning
+abandons
+abbey
+abbeys
+abilities
+ability
+able
+abolish
+abolished
+abolishes
+abolishing
+abolition
+abortion
+abortions
+about
+above
+abroad
+abruptly
+absence
+absences
+absent
+absolute
+absolutely
+absorb
+absorbed
+absorbing
+absorbs
+abstract
+abuse
+abused
+abuses
+abusing
+ac
+academic
+academies
+academy
+accelerate
+accelerated
+accelerates
+accelerating
+accent
+accents
+accept
+acceptable
+acceptance
+acceptances
+accepted
+accepting
+accepts
+access
+accessed
+accesses
+accessible
+accessing
+accident
+accidents
+accommodate
+accommodated
+accommodates
+accommodating
+accommodation
+accommodations
+accompanied
+accompanies
+accompany
+accompanying
+accord
+accorded
+according
+accordingly
+accords
+account
+accountabilities
+accountability
+accountant
+accountants
+accounted
+accounting
+accounts
+accumulate
+accumulated
+accumulates
+accumulating
+accuracy
+accurate
+accurately
+accusation
+accusations
+accuse
+accused
+accuses
+accusing
+ace
+aces
+achieve
+achieved
+achievement
+achievements
+achieves
+achieving
+acid
+acids
+acknowledge
+acknowledged
+acknowledges
+acknowledging
+acquire
+acquired
+acquires
+acquiring
+acquisition
+acquisitions
+acre
+acres
+across
+act
+acted
+acting
+action
+actions
+activate
+activated
+activates
+activating
+active
+actively
+activist
+activists
+activities
+activity
+actor
+actors
+actress
+actresses
+acts
+actual
+actually
+acute
+ad
+adapt
+adaptation
+adaptations
+adapted
+adapting
+adapts
+add
+added
+adding
+addition
+additional
+additions
+address
+addressed
+addresses
+addressing
+adds
+adequate
+adequately
+adjacent
+adjective
+adjectives
+adjust
+adjusted
+adjusting
+adjustment
+adjustments
+adjusts
+administer
+administered
+administering
+administers
+administration
+administrations
+administrative
+administrator
+administrators
+admire
+admired
+admires
+admiring
+admission
+admissions
+admit
+admits
+admitted
+admitting
+adopt
+adopted
+adopting
+adoption
+adoptions
+adopts
+ads
+adult
+adults
+advance
+advanced
+advances
+advancing
+advantage
+advantages
+adventure
+adventures
+adverse
+advertise
+advertised
+advertisement
+advertisements
+advertises
+advertising
+advice
+advise
+advised
+adviser
+advisers
+advises
+advising
+advisory
+advocate
+advocated
+advocates
+advocating
+aesthetic
+affair
+affairs
+affect
+affected
+affecting
+affection
+affections
+affects
+afford
+afforded
+affording
+affords
+afraid
+after
+afternoon
+afternoons
+afterwards
+again
+against
+age
+aged
+ageing
+agencies
+agency
+agenda
+agendas
+agent
+agents
+ages
+aggregate
+aggression
+aggressions
+aggressive
+aging
+ago
+agonies
+agony
+agree
+agreed
+agreeing
+agreement
+agreements
+agrees
+agricultural
+agriculture
+ah
+aha
+ahead
+aid
+aided
+aiding
+aids
+aim
+aimed
+aiming
+aims
+air
+aircraft
+airline
+airlines
+airport
+airports
+airs
+alarm
+alarms
+albeit
+album
+albums
+alcohol
+alcohols
+alert
+alerted
+alerting
+alerts
+alike
+alive
+all
+allegation
+allegations
+allege
+alleged
+allegedly
+alleges
+alleging
+alliance
+alliances
+allied
+allies
+allocate
+allocated
+allocates
+allocating
+allocation
+allocations
+allow
+allowance
+allowances
+allowed
+allowing
+allows
+ally
+almost
+alone
+along
+alongside
+alpha
+alphas
+already
+also
+alter
+alteration
+alterations
+altered
+altering
+alternative
+alternatively
+alternatives
+alters
+although
+altogether
+aluminium
+always
+am
+amateur
+amazing
+ambassador
+ambassadors
+ambiguities
+ambiguity
+ambition
+ambitions
+ambitious
+ambulance
+ambulances
+amend
+amended
+amending
+amendment
+amendments
+amends
+amid
+amnesties
+amnesty
+among
+amongst
+amount
+amounted
+amounting
+amounts
+amusement
+amusements
+an
+analogies
+analogy
+analyse
+analysed
+analyses
+analysing
+analysis
+analyst
+analysts
+ancestor
+ancestors
+ancient
+and
+angel
+angels
+anger
+angers
+angle
+angles
+angrier
+angrily
+angry
+animal
+animals
+ankle
+ankles
+anniversaries
+anniversary
+announce
+announced
+announcement
+announcements
+announces
+announcing
+annual
+annually
+anonymous
+another
+answer
+answered
+answering
+answers
+ant
+antibodies
+antibody
+anticipate
+anticipated
+anticipates
+anticipating
+ants
+anxieties
+anxiety
+anxious
+any
+anybody
+anyone
+anything
+anyway
+anywhere
+apart
+apartment
+apartments
+apologies
+apologise
+apologised
+apologises
+apologising
+apology
+appalling
+apparatus
+apparent
+apparently
+appeal
+appealed
+appealing
+appeals
+appear
+appearance
+appearances
+appeared
+appearing
+appears
+appendices
+appendix
+appetite
+appetites
+apple
+apples
+applicable
+applicant
+applicants
+application
+applications
+applied
+applies
+apply
+applying
+appoint
+appointed
+appointing
+appointment
+appointments
+appoints
+appraisal
+appraisals
+appreciate
+appreciated
+appreciates
+appreciating
+appreciation
+approach
+approached
+approaches
+approaching
+appropriate
+approval
+approvals
+approve
+approved
+approves
+approving
+approximately
+arbitrary
+arch
+archbishop
+archbishops
+arches
+architect
+architects
+architectural
+architecture
+architectures
+archive
+archives
+are
+area
+areas
+argue
+argued
+argues
+arguing
+argument
+arguments
+arise
+arisen
+arises
+arising
+arm
+armed
+armies
+arming
+arms
+army
+arose
+around
+arouse
+aroused
+arouses
+arousing
+arrange
+arranged
+arrangement
+arrangements
+arranges
+arranging
+array
+arrays
+arrest
+arrested
+arresting
+arrests
+arrival
+arrivals
+arrive
+arrived
+arrives
+arriving
+arrow
+arrows
+art
+article
+articles
+artificial
+artist
+artistic
+artists
+arts
+as
+ash
+ashamed
+ashes
+aside
+ask
+asked
+asking
+asks
+asleep
+aspect
+aspects
+aspiration
+aspirations
+assault
+assaults
+assemble
+assembled
+assembles
+assemblies
+assembling
+assembly
+assert
+asserted
+asserting
+assertion
+assertions
+asserts
+assess
+assessed
+assesses
+assessing
+assessment
+assessments
+asset
+assets
+assign
+assigned
+assigning
+assignment
+assignments
+assigns
+assist
+assistance
+assistant
+assistants
+assisted
+assisting
+assists
+associate
+associated
+associates
+associating
+association
+associations
+assume
+assumed
+assumes
+assuming
+assumption
+assumptions
+assurance
+assurances
+assure
+assured
+assures
+assuring
+asylum
+asylums
+at
+ate
+atmosphere
+atmospheres
+atom
+atomic
+atoms
+attach
+attached
+attaches
+attaching
+attack
+attacked
+attacking
+attacks
+attain
+attained
+attaining
+attains
+attempt
+attempted
+attempting
+attempts
+attend
+attendance
+attendances
+attended
+attending
+attends
+attention
+attentions
+attitude
+attitudes
+attract
+attracted
+attracting
+attraction
+attractions
+attractive
+attracts
+attribute
+attributed
+attributes
+attributing
+auction
+auctions
+audience
+audiences
+audit
+auditor
+auditors
+audits
+aunt
+aunts
+author
+authorities
+authority
+authors
+automatic
+automatically
+autonomous
+autonomy
+autumn
+availability
+available
+avenue
+avenues
+average
+averages
+avoid
+avoided
+avoiding
+avoids
+await
+awaited
+awaiting
+awaits
+awake
+award
+awarded
+awarding
+awards
+aware
+awareness
+away
+awful
+awkward
+axes
+axis
+aye
+babies
+baby
+back
+backed
+background
+backgrounds
+backing
+backings
+backs
+backwards
+bacteria
+bacterium
+bad
+bade
+badly
+bag
+bags
+balance
+balanced
+balances
+balancing
+balconies
+balcony
+ball
+ballet
+ballets
+balloon
+balloons
+ballot
+ballots
+balls
+ban
+band
+bands
+bang
+banged
+banging
+bangs
+bank
+banker
+bankers
+banking
+bankruptcies
+bankruptcy
+banks
+banned
+banning
+bans
+bar
+bare
+barely
+barest
+bargain
+bargaining
+bargains
+barn
+barns
+baron
+barons
+barrel
+barrels
+barrier
+barriers
+bars
+base
+based
+bases
+basic
+basically
+basin
+basing
+basins
+basis
+basket
+baskets
+bass
+basses
+bastard
+bastards
+bat
+bath
+bathroom
+bathrooms
+baths
+bats
+batteries
+battery
+battle
+battles
+bay
+bays
+be
+beach
+beaches
+beam
+beams
+bean
+beans
+bear
+bearing
+bearings
+bears
+beast
+beasts
+beat
+beaten
+beating
+beats
+beauties
+beautiful
+beautifully
+beauty
+became
+become
+becomes
+becoming
+bed
+bedroom
+bedrooms
+beds
+bee
+beef
+been
+beer
+beers
+bees
+before
+beg
+began
+begged
+begging
+begin
+beginning
+beginnings
+begins
+begs
+begun
+behalf
+behave
+behaved
+behaves
+behaving
+behaviour
+behaviours
+behind
+being
+beings
+belief
+beliefs
+believe
+believed
+believes
+believing
+bell
+bells
+belong
+belonged
+belonging
+belongs
+below
+belt
+belts
+bench
+benches
+bend
+bending
+bends
+beneath
+beneficial
+benefit
+benefited
+benefiting
+benefits
+benefitted
+benefitting
+bent
+beside
+besides
+best
+bet
+bets
+better
+betting
+between
+beyond
+bias
+bible
+bibles
+bicycle
+bicycles
+bid
+bidden
+bidding
+bids
+big
+bigger
+biggest
+bike
+bikes
+bile
+biles
+bill
+billion
+billions
+bills
+bin
+bind
+binding
+binds
+bins
+biographies
+biography
+biological
+biology
+bird
+birds
+birth
+birthday
+birthdays
+births
+biscuit
+biscuits
+bishop
+bishops
+bit
+bite
+bites
+biting
+bits
+bitter
+bitterly
+bizarre
+black
+blacker
+blackest
+blacks
+bladder
+bladders
+blade
+blades
+blame
+blamed
+blames
+blaming
+blank
+blanket
+blankets
+blast
+blasts
+bless
+blessed
+blesses
+blessing
+blew
+blind
+blinder
+block
+blocked
+blocking
+blocks
+bloke
+blokes
+blood
+bloodiest
+bloods
+bloody
+blow
+blowed
+blowing
+blown
+blows
+blue
+blues
+board
+boards
+boast
+boasted
+boasting
+boasts
+boat
+boats
+bodies
+body
+boil
+boiled
+boiling
+boils
+bold
+bolder
+boldest
+bolt
+bolts
+bomb
+bomber
+bombers
+bombing
+bombings
+bombs
+bond
+bonds
+bone
+bones
+bonus
+bonuses
+book
+booked
+booking
+bookings
+booklet
+booklets
+books
+boom
+booms
+boost
+boosted
+boosting
+boosts
+boot
+boots
+border
+borders
+bore
+bored
+boring
+born
+borne
+borough
+boroughs
+borrow
+borrowed
+borrowing
+borrowings
+borrows
+boss
+bosses
+both
+bother
+bothered
+bothering
+bothers
+bottle
+bottles
+bottom
+bottoms
+bought
+bounce
+bounced
+bounces
+bouncing
+bound
+boundaries
+boundary
+bounded
+bounding
+bounds
+bow
+bowed
+bowel
+bowels
+bowing
+bowl
+bowler
+bowlers
+bowls
+bows
+box
+boxes
+boxing
+boy
+boyfriend
+boyfriends
+boys
+bracket
+brackets
+brain
+brains
+brake
+brakes
+branch
+branches
+brand
+brands
+brass
+brasses
+brave
+braver
+bravest
+breach
+breaches
+bread
+breads
+break
+breakdown
+breakdowns
+breakfast
+breakfasts
+breaking
+breaks
+breast
+breasts
+breath
+breathe
+breathed
+breathes
+breathing
+breaths
+bred
+breed
+breeding
+breeds
+breeze
+breezes
+brethren
+breweries
+brewery
+brick
+bricks
+bride
+brides
+bridge
+bridges
+brief
+briefer
+briefest
+briefly
+brigade
+brigades
+bright
+brighter
+brightest
+brilliant
+bring
+bringing
+brings
+broad
+broadcast
+broadcasting
+broadcasts
+broader
+broadest
+broadly
+brochure
+brochures
+broke
+broken
+broker
+brokers
+bronze
+bronzes
+brother
+brothers
+brought
+brow
+brown
+browner
+brows
+brush
+brushed
+brushes
+brushing
+bucket
+buckets
+budget
+budgets
+build
+builder
+builders
+building
+buildings
+builds
+built
+bulb
+bulbs
+bulk
+bull
+bullet
+bullets
+bulls
+bunch
+bunches
+burden
+burdens
+bureau
+bureaucracies
+bureaucracy
+bureaus
+bureaux
+burial
+burials
+buried
+buries
+burn
+burned
+burning
+burns
+burnt
+burst
+bursting
+bursts
+bury
+burying
+bus
+buses
+bush
+bushes
+busier
+busiest
+business
+businesses
+businessman
+businessmen
+busy
+but
+butter
+butterflies
+butterfly
+butters
+button
+buttons
+buy
+buyer
+buyers
+buying
+buys
+by
+bye
+cab
+cabin
+cabinet
+cabinets
+cabins
+cable
+cables
+cabs
+cage
+cages
+cake
+cakes
+calcium
+calculate
+calculated
+calculates
+calculating
+calculation
+calculations
+calendar
+calendars
+calf
+call
+called
+calling
+calls
+calm
+calmed
+calmer
+calming
+calms
+calves
+came
+camera
+cameras
+camp
+campaign
+campaigned
+campaigning
+campaigns
+camps
+can
+canal
+canals
+cancel
+cancelled
+cancelling
+cancels
+cancer
+cancers
+candidate
+candidates
+candle
+candles
+cans
+canvas
+canvases
+cap
+capabilities
+capability
+capable
+capacities
+capacity
+capital
+capitalism
+capitalist
+capitals
+caps
+captain
+captains
+capture
+captured
+captures
+capturing
+car
+caravan
+caravans
+carbon
+carbons
+card
+cards
+care
+cared
+career
+careers
+careful
+carefully
+carer
+carers
+cares
+cargo
+cargoes
+caring
+carpet
+carpets
+carriage
+carriages
+carried
+carrier
+carriers
+carries
+carry
+carrying
+cars
+cart
+carts
+carve
+carved
+carves
+carving
+case
+cases
+cash
+cassette
+cassettes
+cast
+casting
+castle
+castles
+casts
+casual
+casualties
+casualty
+cat
+catalogue
+catalogues
+catch
+catches
+catching
+categories
+category
+cater
+catered
+catering
+caters
+cathedral
+cathedrals
+catholic
+catholics
+cats
+cattle
+caught
+causal
+cause
+caused
+causes
+causing
+caution
+cautions
+cautious
+cave
+caves
+cease
+ceased
+ceases
+ceasing
+ceiling
+ceilings
+celebrate
+celebrated
+celebrates
+celebrating
+celebration
+celebrations
+cell
+cells
+census
+censuses
+central
+centre
+centred
+centres
+centring
+centuries
+century
+ceremonies
+ceremony
+certain
+certainly
+certainties
+certainty
+certificate
+certificates
+chain
+chains
+chair
+chaired
+chairing
+chairman
+chairmen
+chairs
+challenge
+challenged
+challenges
+challenging
+chamber
+chambers
+champagne
+champagnes
+champion
+champions
+championship
+championships
+chance
+chancellor
+chancellors
+chances
+change
+changed
+changes
+changing
+channel
+channels
+chaos
+chap
+chapel
+chapels
+chaps
+chapter
+chapters
+character
+characterise
+characterised
+characterises
+characterising
+characteristic
+characteristics
+characterize
+characterized
+characterizes
+characterizing
+characters
+charge
+charged
+charges
+charging
+charities
+charity
+charm
+charming
+charms
+chart
+charter
+charters
+charts
+chase
+chased
+chases
+chasing
+chat
+chats
+chatted
+chatting
+cheap
+cheaper
+cheapest
+check
+checked
+checking
+checks
+cheek
+cheeks
+cheer
+cheered
+cheerful
+cheering
+cheese
+cheeses
+chemical
+chemicals
+chemist
+chemistry
+chemists
+cheque
+cheques
+chest
+chests
+chew
+chewed
+chewing
+chews
+chicken
+chickens
+chief
+chiefs
+child
+childhood
+childhoods
+children
+chin
+chins
+chip
+chips
+chocolate
+chocolates
+choice
+choices
+choir
+choirs
+choose
+chooses
+choosing
+chop
+chopped
+chopping
+chops
+chord
+chords
+chorus
+choruses
+chose
+chosen
+chronic
+church
+churches
+cigarette
+cigarettes
+cinema
+cinemas
+circle
+circles
+circuit
+circuits
+circular
+circulate
+circulated
+circulates
+circulating
+circulation
+circulations
+circumstance
+circumstances
+cite
+cited
+cites
+cities
+citing
+citizen
+citizens
+city
+civic
+civil
+civilian
+claim
+claimed
+claiming
+claims
+clarified
+clarifies
+clarify
+clarifying
+clarity
+clash
+clashes
+class
+classes
+classic
+classical
+classics
+classification
+classifications
+classified
+classifies
+classify
+classifying
+classroom
+classrooms
+clause
+clauses
+clay
+clays
+clean
+cleaned
+cleaner
+cleaners
+cleanest
+cleaning
+cleans
+clear
+cleared
+clearer
+clearest
+clearing
+clearly
+clears
+clergy
+clerk
+clerks
+clever
+cleverer
+cleverest
+client
+clients
+cliff
+cliffs
+climate
+climates
+climb
+climbed
+climbing
+climbs
+cling
+clinging
+clings
+clinic
+clinical
+clinics
+clock
+clocks
+close
+closed
+closely
+closer
+closes
+closest
+closing
+closure
+closures
+cloth
+clothes
+clothing
+cloths
+cloud
+clouds
+club
+clubs
+clue
+clues
+clung
+cluster
+clusters
+clutch
+clutched
+clutches
+clutching
+cm
+coach
+coaches
+coal
+coalition
+coalitions
+coals
+coast
+coastal
+coasts
+coat
+coats
+code
+codes
+coffee
+coffees
+coffin
+coffins
+cognitive
+coherent
+coin
+coincide
+coincided
+coincides
+coinciding
+coins
+cold
+colder
+coldest
+colds
+colitis
+collaboration
+collaborations
+collapse
+collapsed
+collapses
+collapsing
+collar
+collars
+colleague
+colleagues
+collect
+collected
+collecting
+collection
+collections
+collective
+collector
+collectors
+collects
+college
+colleges
+colonel
+colonels
+colonial
+colonies
+colony
+colour
+coloured
+colourful
+colouring
+colours
+column
+columns
+combination
+combinations
+combine
+combined
+combines
+combining
+come
+comedies
+comedy
+comes
+cometh
+comfort
+comfortable
+comforted
+comforting
+comforts
+coming
+command
+commanded
+commander
+commanders
+commanding
+commands
+commence
+commenced
+commences
+commencing
+comment
+commentaries
+commentary
+commentator
+commentators
+commented
+commenting
+comments
+commerce
+commercial
+commission
+commissioned
+commissioner
+commissioners
+commissioning
+commissions
+commit
+commitment
+commitments
+commits
+committed
+committee
+committees
+committing
+commodities
+commodity
+common
+commonly
+commonwealth
+communicate
+communicated
+communicates
+communicating
+communication
+communications
+communist
+communists
+communities
+community
+compact
+companies
+companion
+companions
+company
+comparable
+comparative
+comparatively
+compare
+compared
+compares
+comparing
+comparison
+comparisons
+compatible
+compel
+compelled
+compelling
+compels
+compensate
+compensated
+compensates
+compensating
+compensation
+compensations
+compete
+competed
+competence
+competences
+competent
+competes
+competing
+competition
+competitions
+competitive
+competitor
+competitors
+compile
+compiled
+compiles
+compiling
+complain
+complained
+complaining
+complains
+complaint
+complaints
+complete
+completed
+completely
+completes
+completing
+completion
+completions
+complex
+complexes
+complexities
+complexity
+compliance
+complicated
+complication
+complications
+complied
+complies
+comply
+complying
+component
+components
+compose
+composed
+composer
+composers
+composes
+composing
+composition
+compositions
+compound
+compounds
+comprehensive
+comprise
+comprised
+comprises
+comprising
+compromise
+compromises
+compulsory
+computer
+computers
+computing
+conceal
+concealed
+concealing
+conceals
+concede
+conceded
+concedes
+conceding
+conceive
+conceived
+conceives
+conceiving
+concentrate
+concentrated
+concentrates
+concentrating
+concentration
+concentrations
+concept
+conception
+conceptions
+concepts
+conceptual
+concern
+concerned
+concerning
+concerns
+concert
+concerts
+concession
+concessions
+conclude
+concluded
+concludes
+concluding
+conclusion
+conclusions
+concrete
+condemn
+condemned
+condemning
+condemns
+condition
+conditions
+conduct
+conducted
+conducting
+conducts
+confer
+conference
+conferences
+conferred
+conferring
+confers
+confess
+confessed
+confesses
+confessing
+confidence
+confidences
+confident
+confidential
+configuration
+configurations
+confine
+confined
+confines
+confining
+confirm
+confirmation
+confirmations
+confirmed
+confirming
+confirms
+conflict
+conflicts
+conform
+conformed
+conforming
+conforms
+confront
+confrontation
+confrontations
+confronted
+confronting
+confronts
+confuse
+confused
+confuses
+confusing
+confusion
+confusions
+congregation
+congregations
+congress
+congresses
+connect
+connected
+connecting
+connection
+connections
+connects
+conscience
+consciences
+conscious
+consciousness
+consciousnesses
+consensus
+consent
+consents
+consequence
+consequences
+consequently
+conservation
+conservative
+conservatives
+consider
+considerable
+considerably
+consideration
+considerations
+considered
+considering
+considers
+consist
+consisted
+consistent
+consistently
+consisting
+consists
+conspiracies
+conspiracy
+constable
+constables
+constant
+constantly
+constituencies
+constituency
+constituent
+constituents
+constitute
+constituted
+constitutes
+constituting
+constitution
+constitutional
+constitutions
+constraint
+constraints
+construct
+constructed
+constructing
+construction
+constructions
+constructs
+consult
+consultant
+consultants
+consultation
+consultations
+consulted
+consulting
+consults
+consume
+consumed
+consumer
+consumers
+consumes
+consuming
+consumption
+contact
+contacted
+contacting
+contacts
+contain
+contained
+container
+containers
+containing
+contains
+contemplate
+contemplated
+contemplates
+contemplating
+contemporaries
+contemporary
+contempt
+contempts
+content
+contents
+contest
+contests
+context
+contexts
+continent
+continental
+continents
+continually
+continue
+continued
+continues
+continuing
+continuities
+continuity
+continuous
+contract
+contracted
+contracting
+contractor
+contractors
+contracts
+contradiction
+contradictions
+contrary
+contrast
+contrasted
+contrasting
+contrasts
+contribute
+contributed
+contributes
+contributing
+contribution
+contributions
+control
+controlled
+controller
+controllers
+controlling
+controls
+controversial
+controversies
+controversy
+convenient
+convention
+conventional
+conventions
+conversation
+conversations
+conversion
+conversions
+convert
+converted
+converting
+converts
+convey
+conveyed
+conveying
+conveys
+convict
+convicted
+convicting
+conviction
+convictions
+convince
+convinced
+convinces
+convincing
+cook
+cooked
+cooking
+cooks
+cool
+cooled
+cooler
+coolest
+cooling
+cools
+cooperation
+cope
+coped
+copes
+copied
+copies
+coping
+copper
+coppers
+copy
+copying
+copyright
+copyrights
+coral
+corals
+core
+cores
+corn
+corner
+corners
+corns
+corporate
+corporation
+corporations
+corps
+corpse
+corpses
+correct
+corrected
+correcting
+correctly
+corrects
+correlation
+correlations
+correspond
+corresponded
+correspondence
+correspondences
+correspondent
+correspondents
+corresponding
+corresponds
+corridor
+corridors
+corruption
+corruptions
+cost
+costed
+costing
+costlier
+costliest
+costly
+costs
+costume
+costumes
+cottage
+cottages
+cotton
+cottons
+could
+council
+councillor
+councillors
+councils
+counselling
+count
+counted
+counter
+countered
+countering
+counterpart
+counterparts
+counters
+counties
+counting
+countries
+country
+countryside
+counts
+county
+coup
+couple
+coupled
+couples
+coupling
+coups
+courage
+course
+courses
+court
+courtesies
+courtesy
+courts
+cousin
+cousins
+covenant
+covenants
+cover
+coverage
+coverages
+covered
+covering
+covers
+cow
+cows
+crack
+cracked
+cracking
+cracks
+craft
+crafts
+crash
+crashed
+crashes
+crashing
+crawl
+crawled
+crawling
+crawls
+crazier
+craziest
+crazy
+cream
+creams
+create
+created
+creates
+creating
+creation
+creations
+creative
+creature
+creatures
+credit
+credited
+crediting
+creditor
+creditors
+credits
+creep
+creeping
+creeps
+crept
+crew
+crews
+cricket
+crickets
+cried
+cries
+crime
+crimes
+criminal
+criminals
+crises
+crisis
+criteria
+criterion
+critic
+critical
+criticise
+criticised
+criticises
+criticising
+criticism
+criticisms
+criticize
+criticized
+criticizes
+criticizing
+critics
+crop
+crops
+cross
+crossed
+crosses
+crossing
+crossings
+crowd
+crowds
+crown
+crowns
+crucial
+crude
+cruder
+crudest
+cruel
+crueller
+cruellest
+crush
+crushed
+crushes
+crushing
+cry
+crying
+crystal
+crystals
+cult
+cults
+cultural
+culture
+cultures
+cup
+cupboard
+cupboards
+cups
+cure
+cured
+cures
+curing
+curiosities
+curiosity
+curious
+curiouser
+curl
+curled
+curling
+curls
+currencies
+currency
+current
+currently
+currents
+curricula
+curriculum
+curriculums
+curtain
+curtains
+curve
+curves
+custody
+custom
+customer
+customers
+customs
+cut
+cuts
+cutting
+cuttings
+cycle
+cycles
+cylinder
+cylinders
+dad
+daddies
+daddy
+dads
+daily
+dairies
+dairy
+damage
+damaged
+damages
+damaging
+damp
+damper
+dance
+danced
+dancer
+dancers
+dances
+dancing
+danger
+dangerous
+dangers
+dare
+dared
+dares
+daring
+dark
+darker
+darkest
+darkness
+darling
+darlings
+data
+database
+databases
+date
+dated
+dates
+dating
+datum
+daughter
+daughters
+dawn
+dawns
+day
+daylight
+daylights
+days
+de
+dead
+deadline
+deadlines
+deaf
+deal
+dealer
+dealers
+dealing
+dealings
+deals
+dealt
+dear
+dearer
+dearest
+dears
+death
+deaths
+debate
+debated
+debates
+debating
+debt
+debtor
+debtors
+debts
+debut
+debuts
+decade
+decades
+decent
+decide
+decided
+decides
+deciding
+decision
+decisions
+decisive
+deck
+decks
+declaration
+declarations
+declare
+declared
+declares
+declaring
+decline
+declined
+declines
+declining
+decorate
+decorated
+decorates
+decorating
+decoration
+decorations
+decrease
+decreased
+decreases
+decreasing
+decree
+decrees
+dedicate
+dedicated
+dedicates
+dedicating
+deed
+deeds
+deem
+deemed
+deeming
+deems
+deep
+deeper
+deepest
+deeply
+default
+defaults
+defeat
+defeated
+defeating
+defeats
+defect
+defects
+defence
+defences
+defend
+defendant
+defendants
+defended
+defender
+defenders
+defending
+defends
+defensive
+deficiencies
+deficiency
+deficit
+deficits
+define
+defined
+defines
+defining
+definite
+definitely
+definition
+definitions
+degree
+degrees
+delay
+delayed
+delaying
+delays
+delegate
+delegates
+delegation
+delegations
+deliberate
+deliberately
+delicate
+delicious
+delight
+delighted
+delightful
+delights
+deliver
+delivered
+deliveries
+delivering
+delivers
+delivery
+demand
+demanded
+demanding
+demands
+democracies
+democracy
+democrat
+democratic
+democrats
+demolish
+demolished
+demolishes
+demolishing
+demonstrate
+demonstrated
+demonstrates
+demonstrating
+demonstration
+demonstrations
+denied
+denies
+densities
+density
+deny
+denying
+denys
+depart
+departed
+departing
+department
+departments
+departs
+departure
+departures
+depend
+depended
+dependence
+dependent
+depending
+depends
+depict
+depicted
+depicting
+depicts
+deposit
+deposited
+depositing
+deposits
+depressed
+depression
+depressions
+deprive
+deprived
+deprives
+depriving
+depth
+depths
+deputies
+deputy
+derive
+derived
+derives
+deriving
+descend
+descended
+descending
+descends
+descent
+descents
+describe
+described
+describes
+describing
+description
+descriptions
+desert
+deserted
+deserting
+deserts
+deserve
+deserved
+deserves
+design
+designate
+designated
+designates
+designating
+designed
+designer
+designers
+designing
+designs
+desirable
+desire
+desired
+desires
+desiring
+desk
+desks
+desktop
+desktops
+despair
+desperate
+desperately
+despite
+destination
+destinations
+destroy
+destroyed
+destroying
+destroys
+destruction
+detail
+detailed
+details
+detect
+detected
+detecting
+detective
+detectives
+detects
+determination
+determinations
+determine
+determined
+determines
+determining
+develop
+developed
+developer
+developers
+developing
+development
+developments
+develops
+device
+devices
+devil
+devils
+devise
+devised
+devises
+devising
+devote
+devoted
+devotes
+devoting
+diagnose
+diagnosed
+diagnoses
+diagnosing
+diagnosis
+diagram
+diagrams
+dialogue
+dialogues
+diameter
+diameters
+diamond
+diamonds
+diaries
+diary
+dictate
+dictated
+dictates
+dictating
+dictionaries
+dictionary
+did
+die
+died
+dies
+diesel
+diesels
+diet
+diets
+differ
+differed
+difference
+differences
+different
+differentiate
+differentiated
+differentiates
+differentiating
+differently
+differing
+differs
+difficult
+difficulties
+difficulty
+dig
+digging
+digital
+dignities
+dignity
+digs
+dilemma
+dilemmas
+dimension
+dimensions
+diminish
+diminished
+diminishes
+diminishing
+dining
+dinner
+dinners
+dioxide
+dip
+diplomatic
+dipped
+dipping
+dips
+direct
+directed
+directing
+direction
+directions
+directive
+directives
+directly
+director
+directories
+directors
+directory
+directs
+dirt
+dirtier
+dirtiest
+dirty
+disabilities
+disability
+disabled
+disadvantage
+disadvantages
+disagree
+disagreed
+disagreeing
+disagreement
+disagreements
+disagrees
+disappear
+disappeared
+disappearing
+disappears
+disappointed
+disappointment
+disappointments
+disaster
+disasters
+disastrous
+disc
+discharge
+discharged
+discharges
+discharging
+disciplinary
+discipline
+disciplines
+disclose
+disclosed
+discloses
+disclosing
+disclosure
+disclosures
+discount
+discounts
+discourage
+discouraged
+discourages
+discouraging
+discourse
+discourses
+discover
+discovered
+discoveries
+discovering
+discovers
+discovery
+discretion
+discretions
+discrimination
+discriminations
+discs
+discuss
+discussed
+discusses
+discussing
+discussion
+discussions
+disease
+diseases
+dish
+dishes
+disk
+disks
+dislike
+disliked
+dislikes
+disliking
+dismiss
+dismissal
+dismissals
+dismissed
+dismisses
+dismissing
+disorder
+disorders
+display
+displayed
+displaying
+displays
+disposal
+disposals
+dispose
+disposed
+disposes
+disposing
+dispute
+disputes
+dissolve
+dissolved
+dissolves
+dissolving
+distance
+distances
+distant
+distinct
+distinction
+distinctions
+distinctive
+distinguish
+distinguished
+distinguishes
+distinguishing
+distress
+distresses
+distribute
+distributed
+distributes
+distributing
+distribution
+distributions
+district
+districts
+disturb
+disturbance
+disturbances
+disturbed
+disturbing
+disturbs
+dive
+dived
+diverse
+diversities
+diversity
+divert
+diverted
+diverting
+diverts
+dives
+divide
+divided
+dividend
+dividends
+divides
+dividing
+divine
+diving
+division
+divisions
+divorce
+divorced
+divorces
+divorcing
+do
+dock
+docks
+doctor
+doctors
+doctrine
+doctrines
+document
+documentation
+documented
+documenting
+documents
+does
+dog
+dogs
+doing
+doll
+dollar
+dollars
+dolls
+dolphin
+dolphins
+domain
+domains
+domestic
+dominance
+dominant
+dominate
+dominated
+dominates
+dominating
+donate
+donated
+donates
+donating
+donation
+donations
+done
+donor
+donors
+door
+doors
+doorway
+doorways
+dose
+doses
+dot
+doth
+dots
+double
+doubled
+doubles
+doubling
+doubt
+doubted
+doubtful
+doubting
+doubts
+down
+downs
+downstairs
+dozen
+dozens
+draft
+drafted
+drafting
+drafts
+drag
+dragged
+dragging
+dragon
+dragons
+drags
+drain
+drained
+draining
+drains
+drama
+dramas
+dramatic
+dramatically
+drank
+draw
+drawer
+drawers
+drawing
+drawings
+drawn
+draws
+dreadful
+dream
+dreamed
+dreaming
+dreams
+dreamt
+dress
+dressed
+dresses
+dressing
+dressings
+drew
+dried
+drier
+dries
+driest
+drift
+drifted
+drifting
+drifts
+drill
+drilled
+drilling
+drills
+drink
+drinking
+drinks
+drive
+driven
+driver
+drivers
+drives
+driving
+drop
+dropped
+dropping
+drops
+drove
+drown
+drowned
+drowning
+drowns
+drug
+drugs
+drum
+drums
+drunk
+drunker
+dry
+drying
+du
+dual
+duck
+ducks
+due
+dug
+duke
+dukes
+dull
+duller
+dullest
+dump
+dumped
+dumping
+dumps
+duration
+durations
+during
+dust
+dusts
+duties
+duty
+dwelling
+dwellings
+dying
+dynamic
+each
+eager
+eagle
+eagles
+ear
+earl
+earlier
+earliest
+earls
+early
+earn
+earned
+earning
+earnings
+earns
+ears
+earth
+earths
+ease
+eased
+eases
+easier
+easiest
+easily
+easing
+east
+eastern
+easy
+eat
+eaten
+eating
+eats
+echo
+echoed
+echoes
+echoing
+echos
+economic
+economically
+economics
+economies
+economist
+economists
+economy
+ed
+edge
+edges
+edit
+edited
+editing
+edition
+editions
+editor
+editors
+edits
+eds
+educate
+educated
+educates
+educating
+education
+educational
+educations
+effect
+effected
+effecting
+effective
+effectively
+effectiveness
+effects
+efficiencies
+efficiency
+efficient
+efficiently
+effort
+efforts
+eg
+egg
+eggs
+ego
+egos
+eh
+eight
+eighteen
+eighteenth
+eighth
+eighties
+eights
+eighty
+either
+elaborate
+elbow
+elbows
+elder
+elderly
+elders
+eldest
+elect
+elected
+electing
+election
+elections
+electoral
+electorate
+electorates
+electric
+electrical
+electricity
+electron
+electronic
+electronics
+electrons
+elects
+elegant
+element
+elements
+elephant
+elephants
+eleven
+elevens
+eligible
+eliminate
+eliminated
+eliminates
+eliminating
+elite
+elites
+else
+elsewhere
+embark
+embarked
+embarking
+embarks
+embarrassed
+embarrassing
+embarrassment
+embarrassments
+embassies
+embassy
+embodied
+embodies
+embody
+embodying
+embrace
+embraced
+embraces
+embracing
+emerge
+emerged
+emergence
+emergencies
+emergency
+emerges
+emerging
+emission
+emissions
+emotion
+emotional
+emotions
+emperor
+emperors
+emphasis
+emphasise
+emphasised
+emphasises
+emphasising
+emphasize
+emphasized
+emphasizes
+emphasizing
+empire
+empires
+empirical
+employ
+employed
+employee
+employees
+employer
+employers
+employing
+employment
+employments
+employs
+emptied
+emptier
+empties
+empty
+emptying
+enable
+enabled
+enables
+enabling
+enclose
+enclosed
+encloses
+enclosing
+encounter
+encountered
+encountering
+encounters
+encourage
+encouraged
+encouragement
+encouragements
+encourages
+encouraging
+end
+ended
+ending
+endings
+endless
+endorse
+endorsed
+endorses
+endorsing
+ends
+endure
+endured
+endures
+enduring
+enemies
+enemy
+energies
+energy
+enforce
+enforced
+enforcement
+enforces
+enforcing
+engage
+engaged
+engagement
+engagements
+engages
+engaging
+engine
+engineer
+engineering
+engineers
+engines
+enhance
+enhanced
+enhances
+enhancing
+enjoy
+enjoyed
+enjoying
+enjoyment
+enjoyments
+enjoys
+enormous
+enough
+enquire
+enquired
+enquires
+enquiries
+enquiring
+enquiry
+ensure
+ensured
+ensures
+ensuring
+entail
+entailed
+entailing
+entails
+enter
+entered
+entering
+enterprise
+enterprises
+enters
+entertain
+entertained
+entertaining
+entertainment
+entertainments
+entertains
+enthusiasm
+enthusiasms
+enthusiast
+enthusiastic
+enthusiasts
+entire
+entirely
+entities
+entitle
+entitled
+entitles
+entitling
+entity
+entrance
+entrances
+entries
+entry
+envelope
+envelopes
+environment
+environmental
+environments
+envisage
+envisaged
+envisages
+envisaging
+enzyme
+enzymes
+episode
+episodes
+equal
+equalities
+equality
+equalled
+equalling
+equally
+equals
+equation
+equations
+equilibrium
+equip
+equipment
+equipments
+equipped
+equipping
+equips
+equities
+equity
+equivalent
+equivalents
+er
+era
+eras
+erect
+erected
+erecting
+erects
+erm
+erosion
+erosions
+error
+errors
+escape
+escaped
+escapes
+escaping
+especially
+essay
+essays
+essence
+essences
+essential
+essentially
+establish
+established
+establishes
+establishing
+establishment
+establishments
+estate
+estates
+estimate
+estimated
+estimates
+estimating
+etc
+ethical
+ethnic
+evaluate
+evaluated
+evaluates
+evaluating
+evaluation
+evaluations
+even
+evening
+evenings
+event
+events
+eventual
+eventually
+ever
+every
+everybody
+everyday
+everyone
+everything
+everywhere
+evidence
+evidences
+evident
+evidently
+evil
+evils
+evoke
+evoked
+evokes
+evoking
+evolution
+evolutionary
+evolutions
+evolve
+evolved
+evolves
+evolving
+exact
+exactly
+exam
+examination
+examinations
+examine
+examined
+examines
+examining
+example
+examples
+exams
+exceed
+exceeded
+exceeding
+exceeds
+excellent
+except
+exception
+exceptional
+exceptions
+excess
+excesses
+excessive
+exchange
+exchanged
+exchanges
+exchanging
+excited
+excitement
+excitements
+exciting
+exclaim
+exclaimed
+exclaiming
+exclaims
+exclude
+excluded
+excludes
+excluding
+exclusion
+exclusions
+exclusive
+exclusively
+excuse
+excused
+excuses
+excusing
+execute
+executed
+executes
+executing
+execution
+executions
+executive
+executives
+exemption
+exemptions
+exercise
+exercised
+exercises
+exercising
+exert
+exerted
+exerting
+exerts
+exhaust
+exhausted
+exhausting
+exhausts
+exhibit
+exhibited
+exhibiting
+exhibition
+exhibitions
+exhibits
+exile
+exiles
+exist
+existed
+existence
+existences
+existing
+exists
+exit
+exits
+exotic
+expand
+expanded
+expanding
+expands
+expansion
+expansions
+expect
+expectation
+expectations
+expected
+expecting
+expects
+expedition
+expeditions
+expenditure
+expenditures
+expense
+expenses
+expensive
+experience
+experienced
+experiences
+experiencing
+experiment
+experimental
+experiments
+expert
+expertise
+experts
+explain
+explained
+explaining
+explains
+explanation
+explanations
+explicit
+explicitly
+explode
+exploded
+explodes
+exploding
+exploit
+exploitation
+exploited
+exploiting
+exploration
+explorations
+explore
+explored
+explores
+exploring
+explosion
+explosions
+export
+exported
+exporting
+exports
+expose
+exposed
+exposes
+exposing
+exposure
+exposures
+express
+expressed
+expresses
+expressing
+expression
+expressions
+extend
+extended
+extending
+extends
+extension
+extensions
+extensive
+extent
+extents
+external
+extra
+extract
+extracted
+extracting
+extracts
+extraordinary
+extreme
+extremely
+extremes
+eye
+eyebrow
+eyebrows
+eyes
+fabric
+fabrics
+face
+faced
+faces
+facilitate
+facilitated
+facilitates
+facilitating
+facilities
+facility
+facing
+fact
+faction
+factions
+factor
+factories
+factors
+factory
+facts
+faculties
+faculty
+fade
+faded
+fades
+fading
+fail
+failed
+failing
+fails
+failure
+failures
+faint
+fainter
+faintest
+fair
+fairer
+fairest
+fairly
+faith
+faithful
+faiths
+fall
+fallen
+falling
+falls
+fame
+familiar
+families
+family
+famous
+fan
+fancied
+fancies
+fancy
+fancying
+fans
+fantasies
+fantastic
+fantasy
+far
+fare
+fares
+farm
+farmer
+farmers
+farming
+farms
+farther
+farthest
+fascinating
+fashion
+fashionable
+fashions
+fast
+faster
+fastest
+fat
+fatal
+fate
+fates
+father
+fathers
+fats
+fatter
+fattest
+fault
+faults
+favour
+favourable
+favoured
+favouring
+favourite
+favourites
+favours
+fax
+faxes
+fear
+feared
+fearing
+fears
+feather
+feathers
+feature
+featured
+features
+featuring
+fed
+federal
+federation
+federations
+fee
+feed
+feedback
+feedbacks
+feeding
+feeds
+feel
+feeling
+feelings
+feels
+fees
+feet
+fell
+fellow
+fellows
+felt
+female
+females
+feminist
+feminists
+fence
+fences
+ferries
+ferry
+fertility
+festival
+festivals
+fetch
+fetched
+fetches
+fetching
+fever
+fevers
+few
+fewer
+fibre
+fibres
+fiction
+fictions
+field
+fields
+fierce
+fiercer
+fiercest
+fifteen
+fifth
+fifties
+fifty
+fig
+fight
+fighter
+fighters
+fighting
+fights
+figs
+figure
+figured
+figures
+figuring
+file
+filed
+files
+filing
+fill
+filled
+filling
+fills
+film
+films
+filter
+filters
+final
+finally
+finals
+finance
+financed
+finances
+financial
+financing
+find
+finding
+findings
+finds
+fine
+fined
+finer
+fines
+finest
+finger
+fingers
+fining
+finish
+finished
+finishes
+finishing
+fire
+fired
+fires
+firing
+firm
+firmer
+firmest
+firmly
+firms
+first
+firstly
+fiscal
+fish
+fished
+fisherman
+fishermen
+fishes
+fishing
+fist
+fists
+fit
+fitness
+fits
+fitted
+fitter
+fittest
+fitting
+fittings
+five
+fives
+fix
+fixed
+fixes
+fixing
+flag
+flags
+flame
+flames
+flash
+flashed
+flashes
+flashing
+flat
+flats
+flatter
+flavour
+flavours
+fled
+flee
+fleeing
+flees
+fleet
+fleets
+flesh
+flew
+flexibility
+flexible
+flick
+flicked
+flicking
+flicks
+flies
+flight
+flights
+fling
+flinging
+flings
+float
+floated
+floating
+floats
+flock
+flocks
+flood
+flooded
+flooding
+floods
+floor
+floors
+flour
+flourish
+flourished
+flourishes
+flourishing
+flours
+flow
+flowed
+flower
+flowers
+flowing
+flown
+flows
+fluid
+fluids
+flung
+flush
+flushed
+flushes
+flushing
+fly
+flying
+foci
+focus
+focused
+focuses
+focusing
+focussed
+focusses
+focussing
+fog
+fogs
+fold
+folded
+folding
+folds
+folk
+folks
+follies
+follow
+followed
+follower
+followers
+following
+follows
+folly
+fond
+fonder
+fondest
+food
+foods
+fool
+foolish
+fools
+foot
+football
+footballs
+for
+fora
+forbade
+forbid
+forbidden
+forbidding
+forbids
+force
+forced
+forces
+forcing
+forecast
+forecasts
+forehead
+foreheads
+foreign
+foreigner
+foreigners
+forest
+forests
+forever
+forgave
+forget
+forgets
+forgetting
+forgive
+forgiven
+forgives
+forgiving
+forgot
+forgotten
+fork
+forks
+form
+formal
+formally
+format
+formation
+formations
+formats
+formed
+former
+formerly
+formidable
+forming
+forms
+formula
+formulae
+formulas
+formulate
+formulated
+formulates
+formulating
+formulation
+formulations
+forth
+forthcoming
+forties
+fortnight
+fortunate
+fortunately
+fortune
+fortunes
+forty
+forum
+forums
+forward
+forwards
+fossil
+fossils
+foster
+fostered
+fostering
+fosters
+fought
+found
+foundation
+foundations
+founded
+founder
+founders
+founding
+founds
+four
+fours
+fourteen
+fourteens
+fourth
+fox
+foxes
+fraction
+fractions
+fragment
+fragments
+frame
+framed
+frames
+framework
+frameworks
+framing
+fraud
+frauds
+free
+freed
+freedom
+freedoms
+freeing
+freely
+freer
+frees
+freest
+freeze
+freezes
+freezing
+frequencies
+frequency
+frequent
+frequently
+fresh
+fresher
+freshest
+fridge
+fridges
+friend
+friendlier
+friendliest
+friendly
+friends
+friendship
+friendships
+frighten
+frightened
+frightening
+frightens
+fringe
+fringes
+from
+front
+frontier
+frontiers
+fronts
+frown
+frowned
+frowning
+frowns
+froze
+frozen
+fruit
+fruits
+frustration
+frustrations
+ft
+fuel
+fuels
+fulfil
+fulfilled
+fulfilling
+fulfils
+full
+fuller
+fullest
+fully
+fun
+function
+functional
+functioned
+functioning
+functions
+fund
+fundamental
+funded
+funding
+funds
+funeral
+funerals
+funnier
+funniest
+funny
+fur
+furies
+furious
+furnish
+furnished
+furnishes
+furnishing
+furniture
+furs
+further
+furthermore
+furthest
+fury
+fusion
+fusions
+future
+futures
+gain
+gained
+gaining
+gains
+gall
+galleries
+gallery
+galls
+game
+games
+gang
+gangs
+gap
+gaps
+garage
+garages
+garden
+gardener
+gardeners
+gardens
+garment
+garments
+gas
+gases
+gasp
+gasped
+gasping
+gasps
+gasses
+gastric
+gate
+gates
+gather
+gathered
+gathering
+gatherings
+gathers
+gave
+gay
+gaze
+gazed
+gazes
+gazing
+gear
+gears
+gender
+genders
+gene
+general
+generally
+generals
+generate
+generated
+generates
+generating
+generation
+generations
+generous
+genes
+genetic
+genius
+geniuses
+gentle
+gentleman
+gentlemen
+gently
+genuine
+genuinely
+geographical
+geographies
+geography
+gesture
+gestures
+get
+gets
+getting
+ghost
+ghosts
+giant
+giants
+gift
+gifts
+girl
+girlfriend
+girlfriends
+girls
+give
+given
+gives
+giveth
+giving
+glad
+glance
+glanced
+glances
+glancing
+glare
+glared
+glares
+glaring
+glass
+glasses
+glimpse
+glimpses
+global
+glories
+glorious
+glory
+glove
+gloves
+go
+goal
+goals
+goat
+goats
+god
+gods
+goes
+going
+gold
+golden
+golds
+golf
+golfs
+gone
+good
+goodbye
+goodness
+goods
+gospel
+gospels
+got
+gothic
+gotten
+govern
+governed
+governing
+government
+governments
+governor
+governors
+governs
+gown
+gowns
+gp
+gps
+grab
+grabbed
+grabbing
+grabs
+grace
+graces
+grade
+grades
+gradual
+gradually
+graduate
+graduates
+grain
+grains
+grammar
+grammars
+grand
+grander
+grandest
+grandfather
+grandfathers
+grandmother
+grandmothers
+grant
+granted
+granting
+grants
+graph
+graphics
+graphs
+grasp
+grasped
+grasping
+grasps
+grass
+grasses
+grateful
+grave
+gravel
+gravels
+graves
+gravities
+gravity
+great
+greater
+greatest
+greatly
+green
+greener
+greenest
+greenhouse
+greenhouses
+greens
+greet
+greeted
+greeting
+greets
+grew
+grey
+greyer
+grid
+grids
+grief
+griefs
+grim
+grimmer
+grimmest
+grin
+grinned
+grinning
+grins
+grip
+gripped
+gripping
+grips
+gross
+grosser
+ground
+grounds
+group
+grouping
+groupings
+groups
+grow
+growing
+grown
+grows
+growth
+growths
+guarantee
+guaranteed
+guaranteeing
+guarantees
+guard
+guarded
+guardian
+guardians
+guarding
+guards
+guerrilla
+guerrillas
+guess
+guessed
+guesses
+guessing
+guest
+guests
+guidance
+guide
+guided
+guideline
+guidelines
+guides
+guild
+guilds
+guilt
+guilts
+guilty
+guitar
+guitars
+gun
+guns
+guy
+guys
+ha
+habit
+habitat
+habitats
+habits
+had
+hair
+hairs
+half
+halfs
+hall
+halls
+halt
+halted
+halting
+halts
+halves
+hammer
+hammers
+hand
+handed
+handful
+handfuls
+handicap
+handicapped
+handicaps
+handing
+handle
+handled
+handles
+handling
+hands
+handsome
+handsomest
+hang
+hanged
+hanging
+hangs
+happen
+happened
+happening
+happens
+happier
+happiest
+happily
+happiness
+happy
+harbour
+harbours
+hard
+harder
+hardest
+hardly
+hardware
+harm
+harmed
+harming
+harmonies
+harmony
+harms
+harsh
+harsher
+harshest
+harvest
+harvests
+has
+hat
+hate
+hated
+hates
+hating
+hatred
+hatreds
+hats
+haul
+hauled
+hauling
+hauls
+have
+having
+hazard
+hazards
+he
+head
+headache
+headaches
+headed
+heading
+headings
+headline
+headlines
+headmaster
+headmasters
+headquarters
+heads
+health
+healthier
+healthiest
+healthy
+heap
+heaps
+hear
+heard
+hearing
+hearings
+hears
+heart
+hearts
+heat
+heated
+heating
+heats
+heaven
+heavens
+heavier
+heaviest
+heavily
+heavy
+hedge
+hedges
+heel
+heels
+height
+heights
+heir
+heirs
+held
+helicopter
+helicopters
+hell
+hello
+hells
+help
+helped
+helpful
+helping
+helps
+hemisphere
+hemispheres
+hence
+her
+herb
+herbs
+herd
+herds
+here
+heritage
+hero
+heroes
+heros
+hers
+herself
+hesitate
+hesitated
+hesitates
+hesitating
+hey
+hid
+hidden
+hide
+hides
+hiding
+hierarchies
+hierarchy
+high
+higher
+highest
+highlight
+highlighted
+highlighting
+highlights
+highly
+highway
+highways
+hill
+hills
+him
+himself
+hint
+hints
+hip
+hips
+hire
+hired
+hires
+hiring
+his
+historian
+historians
+historic
+historical
+histories
+history
+hit
+hitherto
+hits
+hitting
+hold
+holder
+holders
+holding
+holdings
+holds
+hole
+holes
+holiday
+holidays
+holier
+holiest
+hollies
+holly
+holy
+home
+homeless
+homes
+hon
+honest
+honestly
+honey
+honour
+honoured
+honouring
+honours
+hook
+hooks
+hope
+hoped
+hopefully
+hopes
+hoping
+horizon
+horizons
+horizontal
+horn
+horns
+horrible
+horror
+horrors
+horse
+horses
+hospital
+hospitals
+host
+hostage
+hostages
+hosted
+hostile
+hostilities
+hostility
+hosting
+hosts
+hot
+hotel
+hotels
+hotter
+hottest
+hour
+hours
+house
+housed
+household
+households
+houses
+housewife
+housewives
+housing
+housings
+how
+however
+huge
+human
+humanity
+humans
+humour
+humours
+hundred
+hundreds
+hung
+hunger
+hungrier
+hungry
+hunt
+hunted
+hunting
+hunts
+hurried
+hurries
+hurry
+hurrying
+hurt
+hurting
+hurts
+husband
+husbands
+hut
+huts
+hydrogen
+hypotheses
+hypothesis
+ice
+ices
+idea
+ideal
+ideally
+ideals
+ideas
+identical
+identification
+identifications
+identified
+identifies
+identify
+identifying
+identities
+identity
+ideological
+ideologies
+ideology
+ie
+if
+ignorance
+ignore
+ignored
+ignores
+ignoring
+ill
+illegal
+illness
+illnesses
+illusion
+illusions
+illustrate
+illustrated
+illustrates
+illustrating
+illustration
+illustrations
+image
+images
+imagination
+imaginations
+imaginative
+imagine
+imagined
+imagines
+imagining
+immediate
+immediately
+immense
+immigration
+impact
+impacts
+imperial
+implement
+implementation
+implementations
+implemented
+implementing
+implements
+implication
+implications
+implicit
+implied
+implies
+imply
+implying
+import
+importance
+important
+importantly
+imported
+importing
+imports
+impose
+imposed
+imposes
+imposing
+impossible
+impress
+impressed
+impresses
+impressing
+impression
+impressions
+impressive
+imprisonment
+improve
+improved
+improvement
+improvements
+improves
+improving
+impulse
+impulses
+in
+inability
+inadequate
+inappropriate
+incentive
+incentives
+inch
+inches
+incidence
+incidences
+incident
+incidentally
+incidents
+inclined
+include
+included
+includes
+including
+inclusion
+inclusions
+income
+incomes
+incorporate
+incorporated
+incorporates
+incorporating
+increase
+increased
+increases
+increasing
+increasingly
+incredible
+incur
+incurred
+incurring
+incurs
+indeed
+independence
+independent
+independently
+index
+indexes
+indicate
+indicated
+indicates
+indicating
+indication
+indications
+indicator
+indicators
+indices
+indirect
+indirectly
+individual
+individually
+individuals
+induce
+induced
+induces
+inducing
+indulge
+indulged
+indulges
+indulging
+industrial
+industries
+industry
+inequalities
+inequality
+inevitable
+inevitably
+infant
+infants
+infection
+infections
+inflation
+inflict
+inflicted
+inflicting
+inflicts
+influence
+influenced
+influences
+influencing
+influential
+inform
+informal
+information
+informations
+informed
+informing
+informs
+infrastructure
+infrastructures
+ingredient
+ingredients
+inhabitant
+inhabitants
+inherent
+inherit
+inheritance
+inheritances
+inherited
+inheriting
+inherits
+inhibit
+inhibited
+inhibiting
+inhibits
+initial
+initially
+initiate
+initiated
+initiates
+initiating
+initiative
+initiatives
+inject
+injected
+injecting
+injection
+injections
+injects
+injunction
+injunctions
+injure
+injured
+injures
+injuries
+injuring
+injury
+inland
+inn
+inner
+innocent
+innovation
+innovations
+innovative
+inns
+input
+inputs
+inquiries
+inquiry
+insect
+insects
+insert
+inserted
+inserting
+inserts
+inside
+insider
+insiders
+insides
+insight
+insights
+insist
+insisted
+insisting
+insists
+inspect
+inspected
+inspecting
+inspection
+inspections
+inspector
+inspectors
+inspects
+inspiration
+inspirations
+inspire
+inspired
+inspires
+inspiring
+install
+installation
+installations
+installed
+installing
+installs
+instance
+instances
+instant
+instantly
+instead
+instinct
+instincts
+institute
+institutes
+institution
+institutional
+institutions
+instruct
+instructed
+instructing
+instruction
+instructions
+instructs
+instrument
+instruments
+insufficient
+insurance
+insurances
+insure
+insured
+insures
+insuring
+intact
+intake
+intakes
+integral
+integrate
+integrated
+integrates
+integrating
+integration
+integrity
+intellectual
+intellectuals
+intelligence
+intelligences
+intelligent
+intend
+intended
+intending
+intends
+intense
+intensities
+intensity
+intensive
+intent
+intention
+intentions
+intents
+interaction
+interactions
+interest
+interested
+interesting
+interests
+interface
+interfaces
+interfere
+interfered
+interference
+interferences
+interferes
+interfering
+interim
+interior
+interiors
+intermediate
+internal
+international
+interpret
+interpretation
+interpretations
+interpreted
+interpreting
+interprets
+interrupt
+interrupted
+interrupting
+interrupts
+interval
+intervals
+intervene
+intervened
+intervenes
+intervening
+intervention
+interventions
+interview
+interviewed
+interviewing
+interviews
+intimate
+into
+introduce
+introduced
+introduces
+introducing
+introduction
+introductions
+invade
+invaded
+invades
+invading
+invariably
+invasion
+invasions
+invent
+invented
+inventing
+invention
+inventions
+invents
+invest
+invested
+investigate
+investigated
+investigates
+investigating
+investigation
+investigations
+investigator
+investigators
+investing
+investment
+investments
+investor
+investors
+invests
+invisible
+invitation
+invitations
+invite
+invited
+invites
+inviting
+invoke
+invoked
+invokes
+invoking
+involve
+involved
+involvement
+involvements
+involves
+involving
+iron
+ironies
+irons
+irony
+irrelevant
+is
+isle
+isles
+isolate
+isolated
+isolates
+isolating
+isolation
+issue
+issued
+issues
+issuing
+it
+item
+items
+its
+itself
+jacket
+jackets
+jail
+jails
+jam
+jams
+jar
+jars
+jaw
+jaws
+jazz
+jean
+jeans
+jet
+jets
+jewellery
+job
+jobs
+join
+joined
+joining
+joins
+joint
+jointly
+joints
+joke
+joked
+jokes
+joking
+journal
+journalist
+journalists
+journals
+journey
+journeys
+joy
+joys
+judge
+judged
+judgement
+judgements
+judges
+judging
+judgment
+judgments
+judicial
+juice
+juices
+jump
+jumped
+jumping
+jumps
+junction
+junctions
+jungle
+jungles
+junior
+juries
+jurisdiction
+jurisdictions
+jury
+just
+justice
+justices
+justification
+justifications
+justified
+justifies
+justify
+justifying
+keen
+keener
+keenest
+keep
+keeper
+keepers
+keeping
+keeps
+kept
+key
+keyboard
+keyboards
+keys
+kick
+kicked
+kicking
+kicks
+kid
+kids
+kill
+killed
+killer
+killers
+killing
+killings
+kills
+kilometre
+kilometres
+kind
+kinder
+kindest
+kinds
+king
+kingdom
+kingdoms
+kings
+kiss
+kissed
+kisses
+kissing
+kit
+kitchen
+kitchens
+kits
+km
+kms
+knee
+kneel
+kneeled
+kneeling
+kneels
+knees
+knelt
+knew
+knife
+knight
+knights
+knit
+knits
+knitted
+knitting
+knives
+knock
+knocked
+knocking
+knocks
+knot
+knots
+know
+knowing
+knowledge
+knowledges
+known
+knows
+korean
+la
+lab
+label
+labeled
+labelled
+labelling
+labels
+laboratories
+laboratory
+labour
+labours
+labs
+lace
+laces
+lack
+lacked
+lacking
+lacks
+lad
+ladder
+ladders
+laden
+ladies
+lads
+lady
+laid
+lake
+lakes
+lamb
+lambs
+lamp
+lamps
+land
+landed
+landing
+landings
+landlord
+landlords
+landowner
+landowners
+lands
+landscape
+landscapes
+lane
+lanes
+language
+languages
+lap
+laps
+large
+largely
+larger
+largest
+laser
+lasers
+last
+lasted
+lasting
+lasts
+late
+later
+latest
+latter
+laugh
+laughed
+laughing
+laughs
+laughter
+launch
+launched
+launches
+launching
+law
+lawn
+lawns
+laws
+lawyer
+lawyers
+lay
+layer
+layers
+laying
+layout
+layouts
+lays
+lb
+lbs
+le
+lead
+leader
+leaders
+leadership
+leaderships
+leading
+leads
+leaf
+leaflet
+leaflets
+league
+leagues
+lean
+leaned
+leaning
+leans
+leant
+leap
+leaped
+leaping
+leaps
+leapt
+learn
+learned
+learner
+learners
+learning
+learns
+learnt
+lease
+leases
+least
+leather
+leathers
+leave
+leaves
+leaving
+lecture
+lecturer
+lecturers
+lectures
+led
+left
+lefts
+leg
+legacies
+legacy
+legal
+legally
+legend
+legends
+legislation
+legislative
+legitimate
+legs
+leisure
+lemon
+lemons
+lend
+lending
+lends
+length
+lengthier
+lengths
+lengthy
+lent
+less
+lesser
+lesson
+lessons
+let
+lets
+letter
+letters
+letting
+level
+levelled
+levelling
+levels
+lexical
+liabilities
+liability
+liable
+liaison
+liaisons
+liberal
+liberals
+liberation
+liberties
+liberty
+librarian
+librarians
+libraries
+library
+licence
+licences
+lid
+lids
+lie
+lies
+lieutenant
+lieutenants
+life
+lifes
+lifespan
+lifespans
+lifestyle
+lifestyles
+lifetime
+lifetimes
+lift
+lifted
+lifting
+lifts
+light
+lighted
+lighter
+lightest
+lighting
+lightly
+lights
+like
+liked
+likelier
+likeliest
+likelihood
+likely
+likes
+likewise
+liking
+limb
+limbs
+limit
+limitation
+limitations
+limited
+limiting
+limits
+line
+linear
+lined
+lines
+linguistic
+lining
+link
+linked
+linking
+links
+lion
+lions
+lip
+lips
+liquid
+liquids
+list
+listed
+listen
+listened
+listener
+listeners
+listening
+listens
+listing
+listings
+lists
+lit
+literally
+literary
+literature
+literatures
+little
+live
+lived
+livelier
+liveliest
+lively
+liver
+livers
+lives
+living
+livings
+load
+loaded
+loading
+loads
+loan
+loans
+lobbies
+lobby
+local
+localities
+locality
+locally
+locals
+locate
+located
+locates
+locating
+location
+locations
+loch
+lochs
+lock
+locked
+locking
+locks
+locomotive
+locomotives
+lodge
+lodged
+lodges
+lodging
+log
+logic
+logical
+logics
+logs
+lonelier
+loneliest
+lonely
+long
+longed
+longer
+longest
+longing
+longs
+look
+looked
+looking
+looks
+loop
+loops
+loose
+lord
+lords
+lordship
+lordships
+lorries
+lorry
+lose
+loses
+losing
+loss
+losses
+lost
+lot
+lots
+loud
+louder
+loudest
+loudly
+lounge
+lounges
+love
+loved
+lovelier
+loveliest
+lovely
+lover
+lovers
+loves
+loving
+low
+lower
+lowered
+lowering
+lowers
+lowest
+loyal
+loyalties
+loyalty
+ltd
+luck
+luckier
+luckiest
+lucky
+lump
+lumps
+lunch
+lunches
+lung
+lungs
+luxuries
+luxury
+m
+machine
+machinery
+machines
+mad
+madame
+madder
+made
+magazine
+magazines
+magic
+magistrate
+magistrates
+magnetic
+magnificent
+magnitude
+magnitudes
+maid
+maids
+mail
+mails
+main
+mainframe
+mainframes
+mainland
+mainly
+maintain
+maintained
+maintaining
+maintains
+maintenance
+majesties
+majesty
+major
+majorities
+majority
+majors
+make
+maker
+makers
+makes
+maketh
+making
+makings
+male
+males
+mammal
+mammals
+man
+manage
+managed
+management
+managements
+manager
+managerial
+managers
+manages
+managing
+manipulate
+manipulated
+manipulates
+manipulating
+manner
+manners
+manor
+manors
+mans
+manual
+manuals
+manufacture
+manufactured
+manufacturer
+manufacturers
+manufactures
+manufacturing
+manuscript
+manuscripts
+many
+map
+maps
+marble
+marbles
+march
+marched
+marches
+marching
+margin
+marginal
+margins
+marine
+mark
+marked
+marker
+markers
+market
+marketed
+marketing
+markets
+marking
+marks
+marriage
+marriages
+married
+marries
+marry
+marrying
+marvellous
+mask
+masks
+mass
+masses
+massive
+master
+masters
+match
+matched
+matches
+matching
+mate
+material
+materials
+mates
+mathematical
+mathematics
+matrices
+matrix
+matter
+mattered
+matters
+mature
+maturer
+maturities
+maturity
+maxima
+maximum
+may
+maybe
+mayor
+mayors
+me
+meal
+meals
+mean
+meaner
+meanest
+meaning
+meaningful
+meanings
+means
+meant
+meantime
+meanwhile
+measure
+measured
+measurement
+measurements
+measures
+measuring
+meat
+meats
+mechanic
+mechanical
+mechanics
+mechanism
+mechanisms
+medal
+medals
+media
+medical
+medicine
+medicines
+medieval
+medium
+mediums
+meet
+meeting
+meetings
+meets
+melt
+melted
+melting
+melts
+member
+members
+membership
+memberships
+membrane
+membranes
+memoranda
+memorandum
+memorial
+memorials
+memories
+memory
+men
+mental
+mentally
+mention
+mentioned
+mentioning
+mentions
+menu
+menus
+merchant
+merchants
+mercies
+mercy
+mere
+merely
+merest
+merge
+merged
+merger
+mergers
+merges
+merging
+merit
+merits
+mess
+message
+messages
+messes
+met
+metal
+metals
+metaphor
+metaphors
+method
+methodologies
+methodology
+methods
+metre
+metres
+metropolitan
+mhm
+mice
+mid
+middle
+middles
+midnight
+might
+mightier
+mightiest
+mighty
+migration
+migrations
+mild
+milder
+mildest
+mile
+miles
+military
+milk
+milks
+mill
+million
+millions
+mills
+min
+mind
+minded
+minding
+minds
+mine
+miner
+mineral
+minerals
+miners
+mines
+minima
+minimal
+minimum
+mining
+minister
+ministerial
+ministers
+ministries
+ministry
+minor
+minorities
+minority
+mins
+minus
+minute
+minutes
+miracle
+miracles
+mirror
+mirrors
+miserable
+miseries
+misery
+misleading
+miss
+missed
+misses
+missile
+missiles
+missing
+mission
+missions
+mist
+mistake
+mistaken
+mistakes
+mistaking
+mistook
+mistress
+mistresses
+mists
+mix
+mixed
+mixes
+mixing
+mixture
+mixtures
+ml
+mls
+mm
+mobile
+mobility
+mode
+model
+modelled
+modelling
+models
+moderate
+modern
+modes
+modest
+modification
+modifications
+modified
+modifies
+modify
+modifying
+module
+modules
+molecular
+molecule
+molecules
+moment
+moments
+monarch
+monarchies
+monarchs
+monarchy
+monetary
+money
+moneys
+monitor
+monitored
+monitoring
+monitors
+monk
+monkey
+monkeys
+monks
+monopolies
+monopoly
+monster
+monsters
+month
+monthly
+months
+monument
+monuments
+mood
+moods
+moon
+moons
+moor
+moors
+moral
+morale
+morales
+moralities
+morality
+more
+moreover
+morning
+mornings
+mortalities
+mortality
+mortgage
+mortgages
+mosaic
+mosaics
+most
+mostly
+mother
+mothers
+motif
+motifs
+motion
+motions
+motivate
+motivated
+motivates
+motivating
+motivation
+motivations
+motive
+motives
+motor
+motors
+motorway
+motorways
+mould
+moulds
+mount
+mountain
+mountains
+mounted
+mounting
+mounts
+mouse
+mouses
+mouth
+mouths
+move
+moved
+movement
+movements
+moves
+movie
+movies
+moving
+much
+mucosa
+mucosae
+mud
+muds
+mug
+mugs
+multiple
+multiplied
+multiplies
+multiply
+multiplying
+mum
+mummies
+mummy
+mums
+murder
+murdered
+murderer
+murderers
+murdering
+murders
+murmur
+murmured
+murmuring
+murmurs
+muscle
+muscles
+museum
+museums
+music
+musical
+musician
+musicians
+musics
+must
+mutter
+muttered
+muttering
+mutters
+mutual
+my
+myself
+mysteries
+mysterious
+mystery
+myth
+myths
+nail
+nails
+naked
+name
+named
+namely
+names
+naming
+narrative
+narratives
+narrow
+narrowed
+narrower
+narrowest
+narrowing
+narrows
+nastier
+nastiest
+nasty
+nation
+national
+nationalism
+nationalisms
+nationalist
+nationalists
+nationalities
+nationality
+nations
+native
+natural
+naturally
+nature
+natures
+naval
+navies
+navy
+near
+nearby
+nearer
+nearest
+nearly
+neat
+neater
+neatest
+neatly
+necessarily
+necessary
+necessities
+necessity
+neck
+necks
+need
+needed
+needing
+needle
+needles
+needs
+negative
+neglect
+neglected
+neglecting
+neglects
+negligence
+negotiate
+negotiated
+negotiates
+negotiating
+negotiation
+negotiations
+neighbour
+neighbourhood
+neighbourhoods
+neighbouring
+neighbours
+neither
+nerve
+nerves
+nervous
+nest
+nests
+net
+nets
+network
+networks
+neutral
+never
+nevertheless
+new
+newcomer
+newcomers
+newer
+newest
+newly
+news
+newspaper
+newspapers
+next
+nice
+nicer
+nicest
+night
+nightmare
+nightmares
+nights
+nine
+nines
+nineteen
+nineteens
+nineteenth
+nineties
+ninety
+no
+noble
+nobody
+nod
+nodded
+nodding
+node
+nodes
+nods
+noise
+noises
+noisier
+noisiest
+noisy
+nominate
+nominated
+nominates
+nominating
+none
+nonetheless
+nonsense
+nor
+norm
+normal
+normally
+norms
+north
+northern
+nos
+nose
+noses
+not
+notable
+notably
+note
+notebook
+notebooks
+noted
+notes
+nothing
+notice
+noticed
+notices
+noticing
+noting
+notion
+notions
+novel
+novels
+now
+nowadays
+nowhere
+nuclear
+nuisance
+nuisances
+number
+numbers
+numerous
+nurse
+nurseries
+nursery
+nurses
+nursing
+nut
+nuts
+oak
+oaks
+obey
+obeyed
+obeying
+obeys
+object
+objected
+objecting
+objection
+objections
+objective
+objectives
+objects
+obligation
+obligations
+obliged
+obscure
+obscured
+obscures
+obscuring
+observation
+observations
+observe
+observed
+observer
+observers
+observes
+observing
+obstacle
+obstacles
+obtain
+obtained
+obtaining
+obtains
+obvious
+obviously
+occasion
+occasional
+occasionally
+occasions
+occupation
+occupational
+occupations
+occupied
+occupies
+occupy
+occupying
+occur
+occurred
+occurrence
+occurrences
+occurring
+occurs
+ocean
+oceans
+odd
+odds
+off
+offence
+offences
+offender
+offenders
+offer
+offered
+offering
+offerings
+offers
+office
+officer
+officers
+offices
+official
+officially
+officials
+offset
+offsets
+offsetting
+often
+oh
+oil
+oils
+old
+older
+oldest
+omit
+omits
+omitted
+omitting
+on
+once
+one
+onion
+onions
+only
+onto
+onwards
+ooh
+open
+opened
+opening
+openings
+openly
+opens
+opera
+operas
+operate
+operated
+operates
+operating
+operation
+operational
+operations
+operator
+operators
+opinion
+opinions
+opponent
+opponents
+opportunities
+opportunity
+oppose
+opposed
+opposes
+opposing
+opposite
+opposites
+opposition
+oppositions
+opt
+opted
+optimistic
+opting
+option
+options
+opts
+or
+oral
+orange
+oranges
+orchestra
+orchestras
+order
+ordered
+ordering
+orders
+ordinary
+organ
+organic
+organisation
+organisational
+organisations
+organise
+organised
+organiser
+organisers
+organises
+organising
+organism
+organisms
+organization
+organizations
+organize
+organized
+organizes
+organizing
+organs
+orientation
+orientations
+origin
+original
+originally
+originate
+originated
+originates
+originating
+origins
+orthodox
+other
+others
+otherwise
+ought
+our
+ours
+ourselves
+out
+outbreak
+outbreaks
+outcome
+outcomes
+outdoor
+outer
+outfit
+outfits
+outlet
+outlets
+outline
+outlined
+outlines
+outlining
+outlook
+outlooks
+output
+outputs
+outside
+outsider
+outsiders
+outstanding
+oven
+ovens
+over
+overall
+overcame
+overcome
+overcomes
+overcoming
+overlook
+overlooked
+overlooking
+overlooks
+overnight
+overseas
+overwhelming
+owe
+owed
+owes
+owing
+owl
+owls
+own
+owned
+owner
+owners
+ownership
+owning
+owns
+oxygen
+oxygens
+ozone
+p
+pace
+paces
+pack
+package
+packages
+packed
+packet
+packets
+packing
+packs
+pact
+pacts
+pad
+pads
+page
+pages
+paid
+pain
+painful
+pains
+paint
+painted
+painter
+painters
+painting
+paintings
+paints
+pair
+pairs
+palace
+palaces
+pale
+paler
+palest
+palm
+palms
+pan
+panel
+panels
+panic
+panics
+pans
+paper
+papers
+para
+parade
+parades
+paragraph
+paragraphs
+parallel
+parallels
+parameter
+parameters
+paras
+parcel
+parcels
+pardon
+pardons
+parent
+parental
+parents
+parish
+parishes
+park
+parked
+parking
+parks
+parliament
+parliamentary
+parliaments
+part
+parted
+partial
+partially
+participant
+participants
+participate
+participated
+participates
+participating
+participation
+particle
+particles
+particular
+particularly
+parties
+parting
+partly
+partner
+partners
+partnership
+partnerships
+parts
+party
+pass
+passage
+passages
+passed
+passenger
+passengers
+passes
+passing
+passion
+passions
+passive
+passport
+passports
+past
+pasts
+patch
+patches
+patent
+patents
+path
+paths
+patience
+patient
+patients
+patrol
+patrols
+patron
+patrons
+pattern
+patterns
+pause
+paused
+pauses
+pausing
+pavement
+pavements
+pay
+payable
+payed
+paying
+payment
+payments
+pays
+pc
+pcs
+peace
+peaceful
+peak
+peaks
+peasant
+peasants
+peculiar
+peer
+peered
+peering
+peers
+pen
+penalties
+penalty
+pence
+pencil
+pencils
+penetrate
+penetrated
+penetrates
+penetrating
+pennies
+penny
+pens
+pension
+pensioner
+pensioners
+pensions
+people
+peoples
+pepper
+peppers
+per
+perceive
+perceived
+perceives
+perceiving
+percent
+percentage
+percentages
+perception
+perceptions
+perfect
+perfectly
+perform
+performance
+performances
+performed
+performer
+performers
+performing
+performs
+perhaps
+period
+periods
+permanent
+permanently
+permission
+permissions
+permit
+permits
+permitted
+permitting
+persist
+persisted
+persistent
+persisting
+persists
+person
+personal
+personalities
+personality
+personally
+personnel
+persons
+perspective
+perspectives
+persuade
+persuaded
+persuades
+persuading
+pet
+petition
+petitions
+petrol
+pets
+ph
+phase
+phases
+phenomena
+phenomenon
+philosopher
+philosophers
+philosophical
+philosophies
+philosophy
+phone
+phoned
+phones
+phoning
+photo
+photograph
+photographer
+photographers
+photographs
+photography
+photos
+phrase
+phrases
+physical
+physically
+physics
+piano
+pianos
+pick
+picked
+picking
+picks
+picture
+pictured
+pictures
+picturing
+pie
+piece
+pieces
+pier
+piers
+pies
+pig
+pigs
+pile
+piled
+piles
+piling
+pill
+pillar
+pillars
+pillow
+pillows
+pills
+pilot
+pilots
+pin
+pine
+pines
+pink
+pinker
+pinned
+pinning
+pins
+pint
+pints
+pipe
+pipes
+pit
+pitch
+pitches
+pits
+pity
+place
+placed
+placement
+placements
+places
+placing
+plain
+plainer
+plainest
+plains
+plaintiff
+plaintiffs
+plan
+plane
+planes
+planet
+planets
+planned
+planner
+planners
+planning
+plans
+plant
+planted
+planting
+plants
+plastic
+plastics
+plate
+plates
+platform
+platforms
+play
+played
+player
+players
+playing
+plays
+plc
+plcs
+plea
+plead
+pleaded
+pleading
+pleads
+pleas
+pleasant
+pleasanter
+pleasantest
+please
+pleased
+pleases
+pleasing
+pleasure
+pleasures
+pledge
+pledged
+pledges
+pledging
+plenty
+plot
+plots
+plotted
+plotting
+plunge
+plunged
+plunges
+plunging
+plus
+pm
+pocket
+pockets
+poem
+poems
+poet
+poetry
+poets
+point
+pointed
+pointing
+points
+poison
+poisons
+police
+policeman
+policemen
+policies
+policy
+polite
+politest
+political
+politically
+politician
+politicians
+politics
+poll
+polls
+pollution
+pollutions
+polymer
+polymers
+polytechnic
+polytechnics
+pond
+ponds
+ponies
+pony
+pool
+pools
+poor
+poorer
+poorest
+pop
+popped
+popping
+pops
+popular
+popularity
+population
+populations
+port
+portfolio
+portfolios
+portion
+portions
+portrait
+portraits
+ports
+pose
+posed
+poses
+posing
+position
+positioned
+positioning
+positions
+positive
+positively
+possess
+possessed
+possesses
+possessing
+possession
+possessions
+possibilities
+possibility
+possible
+possibly
+post
+poster
+posters
+postpone
+postponed
+postpones
+posts
+pot
+potato
+potatoes
+potential
+potentially
+potentials
+pots
+pound
+pounds
+pour
+poured
+pouring
+pours
+poverty
+powder
+powders
+power
+powerful
+powers
+pp
+practical
+practically
+practice
+practices
+practise
+practised
+practises
+practising
+practitioner
+practitioners
+praise
+praised
+praises
+praising
+pray
+prayed
+prayer
+prayers
+praying
+prays
+preach
+preached
+preaches
+preaching
+precede
+preceded
+precedent
+precedents
+precedes
+preceding
+precious
+precise
+precisely
+precision
+predator
+predators
+predecessor
+predecessors
+predict
+predicted
+predicting
+prediction
+predictions
+predicts
+predominantly
+prefer
+preference
+preferences
+preferred
+preferring
+prefers
+pregnancies
+pregnancy
+pregnant
+prejudice
+prejudices
+preliminary
+premier
+premise
+premises
+premium
+premiums
+preparation
+preparations
+prepare
+prepared
+prepares
+preparing
+prescribe
+prescribed
+prescribes
+prescribing
+prescription
+prescriptions
+presence
+presences
+present
+presentation
+presentations
+presented
+presenting
+presents
+preservation
+preserve
+preserved
+preserves
+preserving
+presidencies
+presidency
+president
+presidential
+presidents
+press
+pressed
+presses
+pressing
+pressure
+pressures
+presumably
+presume
+presumed
+presumes
+presuming
+pretend
+pretended
+pretending
+pretends
+prettier
+prettiest
+pretty
+prevail
+prevailed
+prevails
+prevent
+prevented
+preventing
+prevention
+prevents
+previous
+previously
+prey
+preys
+price
+priced
+prices
+pricing
+pride
+priest
+priests
+primaries
+primarily
+primary
+prime
+primitive
+prince
+princes
+princess
+princesses
+principal
+principals
+principle
+principles
+print
+printed
+printer
+printers
+printing
+prints
+prior
+priorities
+priority
+prison
+prisoner
+prisoners
+prisons
+privacy
+private
+privately
+privatisation
+privatisations
+privilege
+privileges
+prize
+prizes
+probabilities
+probability
+probable
+probably
+probe
+probes
+problem
+problems
+procedure
+procedures
+proceed
+proceeded
+proceeding
+proceedings
+proceeds
+process
+processed
+processes
+processing
+processor
+processors
+proclaim
+proclaimed
+proclaiming
+proclaims
+produce
+produced
+producer
+producers
+produces
+producing
+product
+production
+productions
+productive
+productivity
+products
+profession
+professional
+professionals
+professions
+professor
+professors
+profile
+profiles
+profit
+profitable
+profits
+profound
+profounder
+profoundest
+program
+programme
+programmes
+programming
+programs
+progress
+progressed
+progresses
+progressing
+progressive
+prohibit
+prohibited
+prohibiting
+prohibits
+project
+projected
+projecting
+projection
+projections
+projects
+prominent
+promise
+promised
+promises
+promising
+promote
+promoted
+promoter
+promoters
+promotes
+promoting
+promotion
+promotions
+prompt
+prompted
+prompting
+prompts
+pronounce
+pronounced
+pronounces
+pronouncing
+proof
+proofs
+propaganda
+proper
+properly
+properties
+property
+proportion
+proportions
+proposal
+proposals
+propose
+proposed
+proposes
+proposing
+proposition
+propositions
+prosecute
+prosecuted
+prosecuting
+prosecution
+prosecutions
+prospect
+prospective
+prospects
+prosperity
+protect
+protected
+protecting
+protection
+protections
+protective
+protects
+protein
+proteins
+protest
+protestant
+protested
+protesting
+protests
+protocol
+protocols
+proud
+prouder
+proudest
+prove
+proved
+proven
+proves
+provide
+provided
+provider
+providers
+provides
+providing
+province
+provinces
+provincial
+proving
+provision
+provisions
+provoke
+provoked
+provokes
+provoking
+ps
+psychiatric
+psychological
+psychologies
+psychologist
+psychologists
+psychology
+pub
+public
+publication
+publications
+publicity
+publicly
+publics
+publish
+published
+publisher
+publishers
+publishes
+publishing
+pubs
+pudding
+puddings
+pull
+pulled
+pulling
+pulls
+pulse
+pulses
+pump
+pumps
+punch
+punches
+punish
+punished
+punishes
+punishing
+punishment
+punishments
+pupil
+pupils
+purchase
+purchased
+purchaser
+purchasers
+purchases
+purchasing
+pure
+purely
+purer
+purest
+purple
+purpose
+purposes
+pursue
+pursued
+pursues
+pursuing
+pursuit
+pursuits
+push
+pushed
+pushes
+pushing
+put
+puts
+putted
+putting
+puzzled
+pylori
+pylorus
+qualification
+qualifications
+qualified
+qualifies
+qualify
+qualifying
+qualities
+quality
+quantities
+quantity
+quarries
+quarry
+quarter
+quarters
+queen
+queens
+queries
+query
+question
+questioned
+questioning
+questionnaire
+questionnaires
+questions
+queue
+queues
+quick
+quicker
+quickest
+quickly
+quid
+quids
+quiet
+quieter
+quietest
+quietly
+quit
+quite
+quits
+quitted
+quitting
+quota
+quotas
+quotation
+quotations
+quote
+quoted
+quotes
+quoting
+qv
+rabbit
+rabbits
+race
+raced
+races
+racial
+racing
+racism
+radiation
+radiations
+radical
+radio
+radios
+rage
+rages
+raid
+raids
+rail
+rails
+railway
+railways
+rain
+rainbow
+rainbows
+rained
+raining
+rains
+raise
+raised
+raises
+raising
+rallies
+rally
+ram
+rams
+ran
+random
+rang
+range
+ranged
+ranger
+rangers
+ranges
+ranging
+rank
+ranks
+rape
+rapes
+rapid
+rapidly
+rare
+rarely
+rarer
+rarest
+rat
+rate
+rated
+rates
+rather
+rating
+ratings
+ratio
+rational
+ratios
+rats
+raw
+reach
+reached
+reaches
+reaching
+react
+reacted
+reacting
+reaction
+reactions
+reactor
+reactors
+reacts
+read
+reader
+readers
+readier
+readily
+reading
+readings
+reads
+ready
+real
+realise
+realised
+realises
+realising
+realistic
+realities
+reality
+realize
+realized
+realizes
+realizing
+really
+realm
+realms
+rear
+rears
+reason
+reasonable
+reasonably
+reasoning
+reasons
+reassure
+reassured
+reassures
+reassuring
+rebel
+rebellion
+rebellions
+rebels
+rebuild
+rebuilding
+rebuilds
+rebuilt
+recall
+recalled
+recalling
+recalls
+receipt
+receipts
+receive
+received
+receiver
+receivers
+receives
+receiving
+recent
+recently
+reception
+receptions
+recession
+recessions
+recipe
+recipes
+recipient
+recipients
+reckon
+reckoned
+reckoning
+reckons
+recognise
+recognised
+recognises
+recognising
+recognition
+recognitions
+recognize
+recognized
+recognizes
+recognizing
+recommend
+recommendation
+recommendations
+recommended
+recommending
+recommends
+reconstruction
+reconstructions
+record
+recorded
+recorder
+recorders
+recording
+recordings
+records
+recover
+recovered
+recoveries
+recovering
+recovers
+recovery
+recruit
+recruited
+recruiting
+recruitment
+recruits
+red
+redder
+reds
+reduce
+reduced
+reduces
+reducing
+reduction
+reductions
+redundancies
+redundancy
+redundant
+ref
+refer
+referee
+referees
+reference
+references
+referenda
+referendum
+referendums
+referral
+referrals
+referred
+referring
+refers
+reflect
+reflected
+reflecting
+reflection
+reflections
+reflects
+reform
+reforms
+refs
+refuge
+refugee
+refugees
+refuges
+refusal
+refusals
+refuse
+refused
+refuses
+refusing
+regain
+regained
+regaining
+regains
+regard
+regarded
+regarding
+regardless
+regards
+regime
+regiment
+regiments
+regimes
+region
+regional
+regions
+register
+registered
+registering
+registers
+registration
+registrations
+regret
+regrets
+regretted
+regretting
+regular
+regularly
+regulate
+regulated
+regulates
+regulating
+regulation
+regulations
+regulatory
+rehearsal
+rehearsals
+reign
+reigns
+reinforce
+reinforced
+reinforces
+reinforcing
+reject
+rejected
+rejecting
+rejection
+rejections
+rejects
+relate
+related
+relates
+relating
+relation
+relations
+relationship
+relationships
+relative
+relatively
+relatives
+relax
+relaxation
+relaxations
+relaxed
+relaxes
+relaxing
+release
+released
+releases
+releasing
+relevance
+relevant
+reliable
+relied
+relief
+reliefs
+relies
+relieve
+relieved
+relieves
+relieving
+religion
+religions
+religious
+reluctance
+reluctant
+rely
+relying
+remain
+remainder
+remainders
+remained
+remaining
+remains
+remark
+remarkable
+remarkably
+remarked
+remarking
+remarks
+remedies
+remedy
+remember
+remembered
+remembering
+remembers
+remind
+reminded
+reminder
+reminders
+reminding
+reminds
+remote
+remoter
+remotest
+removal
+removals
+remove
+removed
+removes
+removing
+renaissance
+render
+rendered
+rendering
+renders
+renew
+renewal
+renewals
+renewed
+renewing
+renews
+rent
+rented
+renting
+rents
+repaid
+repair
+repaired
+repairing
+repairs
+repay
+repaying
+repayment
+repayments
+repays
+repeat
+repeated
+repeatedly
+repeating
+repeats
+repetition
+repetitions
+replace
+replaced
+replacement
+replacements
+replaces
+replacing
+replied
+replies
+reply
+replying
+report
+reported
+reportedly
+reporter
+reporters
+reporting
+reports
+represent
+representation
+representations
+representative
+representatives
+represented
+representing
+represents
+reproduce
+reproduced
+reproduces
+reproducing
+reproduction
+reproductions
+republic
+republican
+republicans
+republics
+reputation
+reputations
+request
+requested
+requesting
+requests
+require
+required
+requirement
+requirements
+requires
+requiring
+rescue
+rescued
+rescues
+rescuing
+research
+researched
+researcher
+researchers
+researches
+researching
+resemble
+resembled
+resembles
+resembling
+resentment
+resentments
+reservation
+reservations
+reserve
+reserved
+reserves
+reserving
+reservoir
+reservoirs
+residence
+residences
+resident
+residential
+residents
+residue
+residues
+resign
+resignation
+resignations
+resigned
+resigning
+resigns
+resist
+resistance
+resistances
+resisted
+resisting
+resists
+resolution
+resolutions
+resolve
+resolved
+resolves
+resolving
+resort
+resorts
+resource
+resources
+respect
+respectable
+respected
+respecting
+respective
+respectively
+respects
+respond
+responded
+respondent
+respondents
+responding
+responds
+response
+responses
+responsibilities
+responsibility
+responsible
+rest
+restaurant
+restaurants
+rested
+resting
+restoration
+restorations
+restore
+restored
+restores
+restoring
+restraint
+restraints
+restrict
+restricted
+restricting
+restriction
+restrictions
+restricts
+rests
+result
+resulted
+resulting
+results
+resume
+resumed
+resumes
+resuming
+retail
+retailer
+retailers
+retain
+retained
+retaining
+retains
+retire
+retired
+retirement
+retirements
+retires
+retiring
+retreat
+retreats
+return
+returned
+returning
+returns
+rev
+reveal
+revealed
+revealing
+reveals
+revelation
+revelations
+revenge
+revenue
+revenues
+reverse
+reversed
+reverses
+reversing
+review
+reviewed
+reviewing
+reviews
+revise
+revised
+revises
+revising
+revision
+revisions
+revival
+revivals
+revive
+revived
+revives
+reviving
+revolution
+revolutionary
+revolutions
+revs
+reward
+rewarded
+rewarding
+rewards
+rhythm
+rhythms
+rib
+ribbon
+ribbons
+ribs
+rice
+rich
+richer
+richest
+rid
+ridden
+ridding
+ride
+rider
+riders
+rides
+ridge
+ridges
+ridiculous
+riding
+rifle
+rifles
+right
+rightly
+rights
+rigid
+ring
+ringing
+rings
+riot
+riots
+rip
+ripped
+ripping
+rips
+rise
+risen
+rises
+rising
+risk
+risked
+risking
+risks
+ritual
+rituals
+rival
+rivals
+river
+rivers
+road
+roads
+roar
+roared
+roaring
+roars
+rob
+robbed
+robbing
+robs
+rock
+rocked
+rocking
+rocks
+rod
+rode
+rods
+role
+roles
+roll
+rolled
+rolling
+rolls
+romance
+romances
+romantic
+roof
+roofs
+room
+rooms
+root
+rooted
+rooting
+roots
+rope
+ropes
+rose
+roses
+rough
+rougher
+roughest
+roughly
+round
+rounded
+rounder
+rounding
+rounds
+route
+routes
+routine
+routines
+row
+rows
+royal
+rub
+rubbed
+rubber
+rubbing
+rubbish
+rubs
+rude
+ruder
+rudest
+rug
+rugby
+rugs
+ruin
+ruins
+rule
+ruled
+ruler
+rulers
+rules
+ruling
+rulings
+rumour
+rumours
+run
+rung
+runner
+runners
+running
+runnings
+runs
+rural
+rush
+rushed
+rushes
+rushing
+sack
+sacked
+sacking
+sacks
+sacred
+sacrifice
+sacrifices
+sad
+sadder
+saddest
+sadly
+safe
+safely
+safer
+safest
+safety
+said
+sail
+sailed
+sailing
+sailor
+sailors
+sails
+saint
+saints
+sake
+sakes
+salad
+salads
+salaries
+salary
+sale
+sales
+salmon
+salt
+salts
+salvation
+same
+sample
+samples
+sanction
+sanctions
+sand
+sands
+sandwich
+sandwiches
+sang
+sank
+sat
+satellite
+satellites
+satisfaction
+satisfactions
+satisfactory
+satisfied
+satisfies
+satisfy
+satisfying
+sauce
+sauces
+save
+saved
+saves
+saving
+savings
+saw
+say
+sayed
+saying
+says
+scale
+scales
+scan
+scandal
+scandals
+scanned
+scanning
+scans
+scarcely
+scared
+scatter
+scattered
+scattering
+scatters
+scene
+scenes
+scent
+scents
+schedule
+scheduled
+schedules
+scheduling
+scheme
+schemes
+scholar
+scholars
+scholarship
+scholarships
+school
+schools
+science
+sciences
+scientific
+scientist
+scientists
+scope
+scopes
+score
+scored
+scores
+scoring
+scrap
+scraps
+scratch
+scratched
+scratches
+scratching
+scream
+screamed
+screaming
+screams
+screen
+screened
+screening
+screens
+screw
+screwed
+screwing
+screws
+script
+scripts
+scrutinies
+scrutiny
+sculpture
+sculptures
+sea
+seal
+sealed
+sealing
+seals
+search
+searched
+searches
+searching
+seas
+season
+seasons
+seat
+seated
+seating
+seats
+second
+secondary
+secondly
+seconds
+secret
+secretaries
+secretary
+secrets
+section
+sections
+sector
+sectors
+secure
+secured
+secures
+securing
+securities
+security
+sediment
+sediments
+see
+seed
+seeds
+seeing
+seek
+seeking
+seeks
+seem
+seemed
+seeming
+seemingly
+seems
+seen
+sees
+segment
+segments
+seize
+seized
+seizes
+seizing
+seldom
+select
+selected
+selecting
+selection
+selections
+selective
+selects
+self
+sell
+seller
+sellers
+selling
+sells
+selves
+semantic
+seminar
+seminars
+senate
+send
+sending
+sends
+senior
+sensation
+sensations
+sense
+sensed
+senses
+sensible
+sensing
+sensitive
+sensitivities
+sensitivity
+sent
+sentence
+sentenced
+sentences
+sentencing
+sentiment
+sentiments
+separate
+separated
+separately
+separates
+separating
+separation
+separations
+sequence
+sequences
+sergeant
+sergeants
+series
+serious
+seriously
+serum
+serums
+servant
+servants
+serve
+served
+server
+servers
+serves
+service
+serviced
+services
+servicing
+serving
+session
+sessions
+set
+sets
+setting
+settings
+settle
+settled
+settlement
+settlements
+settles
+settling
+seven
+sevens
+seventeen
+seventeenth
+seventh
+seventies
+seventy
+several
+severe
+severely
+severest
+sex
+sexes
+sexual
+sexualities
+sexuality
+sexually
+shade
+shades
+shadow
+shadows
+shaft
+shafts
+shake
+shaken
+shakes
+shaking
+shall
+shallow
+shallower
+shallowest
+shame
+shape
+shaped
+shapes
+shaping
+share
+shared
+shareholder
+shareholders
+shares
+sharing
+sharp
+sharply
+she
+shed
+shedding
+sheds
+sheep
+sheer
+sheet
+sheets
+shelf
+shell
+shells
+shelter
+shelters
+shelves
+shield
+shields
+shift
+shifted
+shifting
+shifts
+shilling
+shillings
+shine
+shined
+shines
+shining
+ship
+shipped
+shipping
+ships
+shirt
+shirts
+shiver
+shivered
+shivering
+shivers
+shock
+shocked
+shocks
+shoe
+shoes
+shone
+shook
+shoot
+shooting
+shootings
+shoots
+shop
+shopped
+shopping
+shops
+shore
+shores
+short
+shortage
+shortages
+shorter
+shortest
+shortly
+shot
+shots
+should
+shoulder
+shoulders
+shout
+shouted
+shouting
+shouts
+show
+showed
+shower
+showers
+showing
+shown
+shows
+shrug
+shrugged
+shrugging
+shrugs
+shut
+shuts
+shutting
+shy
+shyer
+sick
+sicker
+sickness
+sicknesses
+side
+sides
+sigh
+sighed
+sighing
+sighs
+sight
+sights
+sign
+signal
+signalled
+signalling
+signals
+signature
+signatures
+signed
+significance
+significances
+significant
+significantly
+signing
+signs
+silence
+silences
+silent
+silently
+silk
+silks
+sillier
+silliest
+silly
+silver
+similar
+similarities
+similarity
+similarly
+simple
+simpler
+simplest
+simply
+simultaneously
+sin
+since
+sincerely
+sing
+singer
+singers
+singing
+single
+singles
+sings
+sink
+sinking
+sinks
+sins
+sir
+sirs
+sister
+sisters
+sit
+site
+sites
+sits
+sitting
+situate
+situated
+situates
+situating
+situation
+situations
+six
+sixes
+sixteen
+sixth
+sixties
+sixty
+size
+sizes
+sketch
+sketches
+skies
+skill
+skilled
+skills
+skin
+skins
+skirt
+skirts
+skull
+skulls
+sky
+slam
+slammed
+slamming
+slams
+slave
+slaves
+sleep
+sleeping
+sleeps
+sleeve
+sleeves
+slept
+slice
+slices
+slid
+slide
+slides
+sliding
+slight
+slighter
+slightest
+slightly
+slim
+slimmer
+slimmest
+slip
+slipped
+slipping
+slips
+slope
+slopes
+slow
+slowed
+slower
+slowest
+slowing
+slowly
+slows
+small
+smaller
+smallest
+smart
+smarter
+smartest
+smash
+smashed
+smashes
+smashing
+smell
+smelled
+smelling
+smells
+smelt
+smile
+smiled
+smiles
+smiling
+smoke
+smoked
+smokes
+smoking
+smooth
+smoothed
+smoother
+smoothest
+smoothing
+smooths
+snake
+snakes
+snap
+snapped
+snapping
+snaps
+snatch
+snatched
+snatches
+snatching
+sniff
+sniffed
+sniffing
+sniffs
+snow
+snows
+so
+soap
+soaps
+soccer
+social
+socialism
+socialist
+socially
+societies
+society
+sociology
+sock
+socks
+sofa
+sofas
+soft
+softer
+softest
+softly
+software
+soil
+soils
+solar
+sold
+soldier
+soldiers
+sole
+solely
+solicitor
+solicitors
+solid
+solidarities
+solidarity
+solo
+solos
+solution
+solutions
+solve
+solved
+solves
+solving
+some
+somebody
+somehow
+someone
+something
+sometimes
+somewhat
+somewhere
+son
+song
+songs
+sons
+soon
+sooner
+sophisticated
+sorrier
+sorry
+sort
+sorted
+sorting
+sorts
+sought
+soul
+souls
+sound
+sounded
+sounder
+soundest
+sounding
+sounds
+soup
+soups
+source
+sources
+south
+southern
+sovereignty
+space
+spaces
+spare
+spared
+spares
+sparing
+spat
+spatial
+speak
+speaker
+speakers
+speaking
+speaks
+special
+specialise
+specialised
+specialises
+specialising
+specialist
+specialists
+specially
+species
+specific
+specifically
+specification
+specifications
+specified
+specifies
+specify
+specifying
+specimen
+specimens
+spectacle
+spectacles
+spectacular
+spectator
+spectators
+spectra
+spectrum
+speculation
+speculations
+sped
+speech
+speeches
+speed
+speeded
+speeding
+speeds
+spell
+spelled
+spelling
+spellings
+spells
+spelt
+spend
+spending
+spends
+spent
+sphere
+spheres
+spider
+spiders
+spill
+spilled
+spilling
+spills
+spilt
+spin
+spine
+spines
+spinning
+spins
+spirit
+spirits
+spiritual
+spit
+spits
+spitting
+splendid
+split
+splits
+splitting
+spoil
+spoiled
+spoiling
+spoils
+spoilt
+spoke
+spoken
+spokesman
+spokesmen
+sponsor
+sponsored
+sponsoring
+sponsors
+sponsorship
+sponsorships
+spontaneous
+sport
+sporting
+sports
+spot
+spots
+spotted
+spotting
+sprang
+spread
+spreading
+spreads
+spring
+springing
+springs
+sprung
+spun
+spur
+spurs
+squad
+squadron
+squadrons
+squads
+square
+squares
+squeeze
+squeezed
+squeezes
+squeezing
+stab
+stabbed
+stabbing
+stability
+stable
+stabs
+stadia
+stadium
+stadiums
+staff
+staffs
+stage
+staged
+stages
+staging
+stair
+staircase
+staircases
+stairs
+stake
+stakes
+stall
+stalls
+stamp
+stamped
+stamping
+stamps
+stance
+stances
+stand
+standard
+standards
+standing
+standings
+stands
+star
+stare
+stared
+stares
+staring
+stars
+start
+started
+starting
+starts
+state
+stated
+statement
+statements
+states
+static
+stating
+station
+stations
+statistical
+statistics
+statue
+statues
+status
+statute
+statutes
+statutory
+staves
+stay
+stayed
+staying
+stays
+steadier
+steadily
+steady
+steal
+stealing
+steals
+steam
+steams
+steel
+steels
+steep
+steeper
+steepest
+steer
+steered
+steering
+steers
+stem
+stemmed
+stemming
+stems
+step
+stepped
+stepping
+steps
+sterling
+steward
+stewards
+stick
+sticking
+sticks
+stiff
+stiffer
+stiffest
+still
+stimulate
+stimulated
+stimulates
+stimulating
+stimuli
+stimulus
+stir
+stirred
+stirring
+stirs
+stitch
+stitches
+stock
+stocks
+stole
+stolen
+stomach
+stomachs
+stone
+stones
+stood
+stool
+stools
+stop
+stopped
+stopping
+stops
+storage
+store
+stored
+stores
+stories
+storing
+storm
+storms
+story
+straight
+straighten
+straightened
+straightening
+straightens
+straighter
+straightest
+straightforward
+strain
+strained
+straining
+strains
+strand
+strands
+strange
+strangely
+stranger
+strangers
+strangest
+strategic
+strategies
+strategy
+straw
+straws
+stream
+streams
+street
+streets
+strength
+strengthen
+strengthened
+strengthening
+strengthens
+strengths
+stress
+stressed
+stresses
+stressing
+stretch
+stretched
+stretches
+stretching
+strict
+stricter
+strictest
+strictly
+stride
+strides
+striding
+strike
+striker
+strikers
+strikes
+striking
+string
+strings
+strip
+stripped
+stripping
+strips
+strive
+strived
+striven
+strives
+striving
+strode
+stroke
+stroked
+strokes
+stroking
+strong
+stronger
+strongest
+strongly
+strove
+struck
+structural
+structure
+structures
+struggle
+struggled
+struggles
+struggling
+stuck
+student
+students
+studied
+studies
+studio
+studios
+study
+studying
+stuff
+stuffed
+stuffing
+stuffs
+stumble
+stumbled
+stumbles
+stumbling
+stupid
+style
+styles
+subject
+subjected
+subjecting
+subjective
+subjects
+submission
+submissions
+submit
+submits
+submitted
+submitting
+subscription
+subscriptions
+subsequent
+subsequently
+subsidiaries
+subsidiary
+subsidies
+subsidy
+substance
+substances
+substantial
+substantially
+substitute
+substituted
+substitutes
+substituting
+subtle
+suburb
+suburbs
+succeed
+succeeded
+succeeding
+succeeds
+success
+successes
+successful
+successfully
+succession
+successions
+successive
+successor
+successors
+such
+suck
+sucked
+sucking
+sucks
+sudden
+suddenly
+sue
+sued
+sueing
+sues
+suffer
+suffered
+sufferer
+sufferers
+suffering
+sufferings
+suffers
+sufficient
+sufficiently
+sugar
+sugars
+suggest
+suggested
+suggesting
+suggestion
+suggestions
+suggests
+suicide
+suicides
+suing
+suit
+suitable
+suite
+suited
+suites
+suiting
+suits
+sum
+summaries
+summarise
+summarised
+summarises
+summarising
+summary
+summed
+summer
+summers
+summing
+summit
+summits
+summon
+summoned
+summoning
+sums
+sun
+sung
+sunk
+sunlight
+sunnier
+sunniest
+sunny
+suns
+sunshine
+super
+superb
+superintendent
+superintendents
+superior
+supermarket
+supermarkets
+supervise
+supervised
+supervises
+supervising
+supervision
+supervisor
+supervisors
+supper
+suppers
+supplement
+supplemented
+supplementing
+supplements
+supplied
+supplier
+suppliers
+supplies
+supply
+supplying
+support
+supported
+supporter
+supporters
+supporting
+supports
+suppose
+supposed
+supposes
+supposing
+suppress
+suppressed
+suppresses
+suppressing
+supreme
+sure
+surely
+surer
+surest
+surface
+surfaces
+surgeon
+surgeons
+surgeries
+surgery
+surplus
+surprise
+surprised
+surprises
+surprising
+surprisingly
+surrender
+surrendered
+surrendering
+surrenders
+surround
+surrounded
+surrounding
+surroundings
+surrounds
+survey
+surveyed
+surveying
+surveyor
+surveyors
+surveys
+survival
+survivals
+survive
+survived
+survives
+surviving
+survivor
+survivors
+suspect
+suspected
+suspecting
+suspects
+suspend
+suspended
+suspending
+suspends
+suspension
+suspensions
+suspicion
+suspicions
+suspicious
+sustain
+sustained
+sustaining
+sustains
+swallow
+swallowed
+swallowing
+swallows
+swam
+swear
+swearing
+swears
+sweat
+sweats
+sweep
+sweeping
+sweeps
+sweet
+sweeter
+sweetest
+swell
+swelled
+swelling
+swells
+swept
+swiftly
+swim
+swimming
+swims
+swing
+swinging
+swings
+switch
+switched
+switches
+switching
+swollen
+sword
+swords
+swore
+sworn
+swum
+swung
+symbol
+symbolic
+symbols
+sympathetic
+sympathies
+sympathy
+symptom
+symptoms
+syndrome
+syndromes
+syntheses
+synthesis
+system
+systematic
+systems
+table
+tables
+tablet
+tablets
+tackle
+tackled
+tackles
+tackling
+tactic
+tactics
+tail
+tails
+take
+taken
+takeover
+takeovers
+takes
+taking
+tale
+talent
+talents
+tales
+talk
+talked
+talking
+talks
+tall
+taller
+tallest
+tank
+tanks
+tap
+tape
+tapes
+tapped
+tapping
+taps
+target
+targeted
+targeting
+targets
+targetted
+targetting
+tariff
+tariffs
+task
+tasks
+taste
+tasted
+tastes
+tasting
+taught
+tax
+taxation
+taxed
+taxes
+taxi
+taxing
+taxis
+taxpayer
+taxpayers
+tea
+teach
+teacher
+teachers
+teaches
+teaching
+teachings
+team
+teams
+tear
+tearing
+tears
+teas
+technical
+technically
+technique
+techniques
+technological
+technologies
+technology
+teenage
+teenager
+teenagers
+teeth
+tel
+telecommunication
+telecommunications
+telegraph
+telegraphs
+telephone
+telephoned
+telephones
+telephoning
+television
+televisions
+tell
+telling
+tells
+temper
+temperature
+temperatures
+tempers
+temple
+temples
+temporarily
+temporary
+tempt
+temptation
+temptations
+tempted
+tempting
+tempts
+ten
+tenant
+tenants
+tend
+tended
+tendencies
+tendency
+tender
+tending
+tends
+tennis
+tens
+tension
+tensions
+tent
+tenth
+tents
+term
+termed
+terminal
+terminals
+terminate
+terminated
+terminates
+terminating
+terms
+terrace
+terraces
+terrible
+terribly
+territorial
+territories
+territory
+terror
+terrorist
+terrorists
+terrors
+test
+testament
+testaments
+tested
+testing
+tests
+text
+textile
+textiles
+texts
+texture
+textures
+than
+thank
+thanked
+thanking
+thanks
+that
+the
+theatre
+theatres
+thee
+theft
+thefts
+their
+theirs
+theirselves
+them
+theme
+themes
+themselves
+then
+theologies
+theology
+theoretical
+theories
+theory
+therapies
+therapy
+there
+thereafter
+thereby
+therefore
+these
+theses
+thesis
+they
+thick
+thicker
+thickest
+thief
+thieves
+thigh
+thighs
+thin
+thing
+things
+think
+thinking
+thinks
+thinner
+thinnest
+third
+thirteen
+thirties
+thirty
+this
+thorough
+thoroughly
+those
+thou
+though
+thought
+thoughts
+thousand
+thousands
+thread
+threads
+threat
+threaten
+threatened
+threatening
+threatens
+threats
+three
+threes
+threshold
+thresholds
+threw
+throat
+throats
+throne
+thrones
+through
+throughout
+throw
+throwing
+thrown
+throws
+thrust
+thrusting
+thrusts
+thumb
+thumbs
+thus
+ticket
+tickets
+tide
+tides
+tie
+tied
+ties
+tiger
+tigers
+tight
+tighten
+tightened
+tightening
+tightens
+tighter
+tightest
+tightly
+tile
+tiles
+till
+timber
+timbers
+time
+timed
+times
+timetable
+timetables
+timing
+timings
+tin
+tinier
+tiniest
+tins
+tiny
+tip
+tipped
+tipping
+tips
+tired
+tissue
+tissues
+title
+titles
+to
+toast
+toasts
+tobacco
+today
+toe
+toes
+together
+toilet
+toilets
+told
+tolerate
+tolerated
+tolerates
+tolerating
+tomato
+tomatoes
+tomorrow
+ton
+tone
+tones
+tongue
+tongues
+tonight
+tonne
+tonnes
+tons
+too
+took
+tool
+tools
+tooth
+top
+topic
+topics
+topped
+topping
+tops
+torch
+torches
+tore
+torn
+toss
+tossed
+tosses
+tossing
+total
+totalled
+totalling
+totally
+totals
+touch
+touched
+touches
+touching
+tough
+tougher
+toughest
+tour
+toured
+touring
+tourism
+tourist
+tourists
+tournament
+tournaments
+tours
+toward
+towards
+towel
+towels
+tower
+towers
+town
+towns
+toxic
+toy
+toys
+trace
+traced
+traces
+tracing
+track
+tracks
+trade
+traded
+trader
+traders
+trades
+trading
+tradition
+traditional
+traditionally
+traditions
+traffic
+tragedies
+tragedy
+tragic
+trail
+trailed
+trailing
+trails
+train
+trained
+trainee
+trainees
+trainer
+trainers
+training
+trains
+transaction
+transactions
+transfer
+transferred
+transferring
+transfers
+transform
+transformation
+transformations
+transformed
+transforming
+transforms
+transition
+transitions
+translate
+translated
+translates
+translating
+translation
+translations
+transmission
+transmissions
+transmit
+transmits
+transmitted
+transmitting
+transport
+transported
+transporting
+transports
+trap
+trapped
+trapping
+traps
+travel
+traveling
+travelled
+traveller
+travellers
+travelling
+travels
+tray
+trays
+treasure
+treasures
+treasuries
+treasury
+treat
+treated
+treaties
+treating
+treatment
+treatments
+treats
+treaty
+tree
+trees
+tremble
+trembled
+trembles
+trembling
+tremendous
+trend
+trends
+trial
+trials
+triangle
+triangles
+tribe
+tribes
+tribunal
+tribunals
+tribute
+tributes
+trick
+tricks
+tried
+tries
+trigger
+triggered
+triggering
+triggers
+trip
+trips
+triumph
+triumphs
+troop
+troops
+trophies
+trophy
+tropical
+trouble
+troubled
+troubles
+troubling
+trouser
+trousers
+truck
+trucks
+truer
+truest
+truly
+trunk
+trunks
+trust
+trusted
+trustee
+trustees
+trusting
+trusts
+truth
+truths
+try
+trying
+tube
+tubes
+tuck
+tucked
+tucking
+tucks
+tumour
+tumours
+tune
+tunes
+tunnel
+tunnels
+turn
+turned
+turning
+turnover
+turnovers
+turns
+tutor
+tutors
+twelve
+twelves
+twenties
+twentieth
+twenty
+twice
+twin
+twins
+twist
+twisted
+twisting
+twists
+two
+twos
+tying
+type
+typed
+types
+typical
+typically
+typing
+tyre
+tyres
+uglier
+ugliest
+ugly
+ulcer
+ulcers
+ultimate
+ultimately
+unable
+unacceptable
+unaware
+uncertain
+uncertainties
+uncertainty
+unchanged
+uncle
+uncles
+uncomfortable
+unconscious
+under
+undergo
+undergoes
+undergoing
+undergone
+underground
+underline
+underlined
+underlines
+underlining
+underlying
+undermine
+undermined
+undermines
+undermining
+underneath
+understand
+understanding
+understandings
+understands
+understood
+undertake
+undertaken
+undertakes
+undertaking
+undertakings
+undertook
+underwent
+undoubtedly
+unemployed
+unemployment
+unexpected
+unfair
+unfortunate
+unfortunately
+unhappier
+unhappiest
+unhappy
+uniform
+uniforms
+union
+unionist
+unionists
+unions
+unique
+unit
+unite
+united
+unites
+unities
+uniting
+units
+unity
+universal
+universe
+universes
+universities
+university
+unknown
+unless
+unlike
+unlikeliest
+unlikely
+unnecessary
+unpleasant
+until
+unusual
+unusually
+unwilling
+up
+update
+updated
+updates
+updating
+upon
+upper
+upset
+upsets
+upsetting
+upstairs
+upwards
+urban
+urge
+urged
+urgent
+urges
+urging
+us
+usage
+usages
+use
+used
+useful
+useless
+user
+users
+uses
+using
+usual
+usually
+utilities
+utility
+utterance
+utterances
+utterly
+v
+vague
+valid
+validity
+valley
+valleys
+valuable
+valuation
+valuations
+value
+valued
+values
+valuing
+valve
+valves
+van
+vanish
+vanished
+vanishes
+vanishing
+vans
+variable
+variables
+variant
+variants
+variation
+variations
+varied
+varies
+varieties
+variety
+various
+vary
+varying
+vast
+vaster
+vegetable
+vegetables
+vegetation
+vehicle
+vehicles
+vein
+veins
+velocities
+velocity
+vendor
+vendors
+venture
+ventured
+ventures
+venturing
+venue
+venues
+verb
+verbal
+verbs
+verdict
+verdicts
+verse
+verses
+version
+versions
+vertical
+very
+vessel
+vessels
+via
+victim
+victims
+victories
+victory
+video
+videos
+view
+viewed
+viewer
+viewers
+viewing
+viewpoint
+viewpoints
+views
+villa
+village
+villages
+villas
+violence
+violent
+virgin
+virgins
+virtually
+virtue
+virtues
+virus
+viruses
+visible
+vision
+visions
+visit
+visited
+visiting
+visitor
+visitors
+visits
+visual
+vital
+vitamin
+vitamins
+vivid
+vocabularies
+vocabulary
+vocational
+voice
+voiced
+voices
+voicing
+vol
+vols
+voltage
+voltages
+volume
+volumes
+voluntary
+volunteer
+volunteers
+von
+vote
+voted
+voter
+voters
+votes
+voting
+vulnerable
+wage
+wages
+waist
+waists
+wait
+waited
+waiter
+waiters
+waiting
+waits
+wake
+wakes
+waking
+walk
+walked
+walking
+walks
+wall
+walls
+wan
+wander
+wandered
+wandering
+wanders
+want
+wanted
+wanting
+wants
+war
+ward
+wardrobe
+wardrobes
+wards
+warehouse
+warehouses
+warm
+warmed
+warmer
+warmest
+warming
+warms
+warmth
+warn
+warned
+warning
+warnings
+warns
+warrant
+warrants
+warrior
+warriors
+wars
+wartime
+was
+wash
+washed
+washes
+washing
+washings
+waste
+wasted
+wastes
+wasting
+watch
+watched
+watches
+watching
+water
+waters
+wave
+waved
+waves
+waving
+way
+ways
+we
+weak
+weaken
+weakened
+weakening
+weakens
+weaker
+weakest
+weakness
+weaknesses
+wealth
+wealthier
+wealthiest
+wealthy
+weapon
+weapons
+wear
+wearing
+wears
+weather
+weathers
+weave
+weaved
+weaves
+weaving
+wedding
+weddings
+wee
+week
+weekend
+weekends
+weekly
+weeks
+weep
+weeping
+weeps
+weigh
+weighed
+weighing
+weighs
+weight
+weights
+weird
+welcome
+welcomed
+welcomes
+welcoming
+welfare
+well
+wells
+went
+wept
+were
+west
+western
+wet
+wetter
+wettest
+whale
+whales
+what
+whatever
+wheat
+wheats
+wheel
+wheels
+when
+whenever
+where
+whereas
+whereby
+wherever
+whether
+which
+while
+whilst
+whiskies
+whisky
+whisper
+whispered
+whispering
+whispers
+white
+whiter
+whites
+whitest
+who
+whoever
+whole
+wholes
+wholly
+whom
+whose
+why
+wicked
+wicket
+wickets
+wide
+widely
+widen
+widened
+widening
+widens
+wider
+widespread
+widest
+widow
+widows
+width
+widths
+wife
+wild
+wilder
+wildest
+wildlife
+will
+willing
+willingness
+wills
+win
+wind
+winded
+winding
+window
+windows
+winds
+wine
+wines
+wing
+wings
+winner
+winners
+winning
+wins
+winter
+winters
+wipe
+wiped
+wipes
+wiping
+wire
+wires
+wisdom
+wisdoms
+wise
+wiser
+wisest
+wish
+wished
+wishes
+wishing
+wit
+with
+withdraw
+withdrawal
+withdrawals
+withdrawing
+withdrawn
+withdraws
+withdrew
+within
+without
+witness
+witnessed
+witnesses
+witnessing
+wits
+wives
+woke
+woken
+wolf
+wolves
+woman
+women
+won
+wonder
+wondered
+wonderful
+wondering
+wonders
+wood
+wooden
+woodland
+woodlands
+woods
+wool
+wools
+word
+words
+wore
+work
+worked
+worker
+workers
+workforce
+workforces
+working
+workings
+works
+workshop
+workshops
+workstation
+workstations
+world
+worlds
+worldwide
+worm
+worms
+worn
+worried
+worries
+worry
+worrying
+worse
+worship
+worships
+worst
+worth
+worthier
+worthwhile
+worthy
+would
+wound
+wounded
+wounding
+wounds
+wove
+woven
+wrap
+wrapped
+wrapping
+wraps
+wrist
+wrists
+write
+writer
+writers
+writes
+writing
+writings
+written
+wrong
+wrote
+wrought
+x
+ya
+yacht
+yachts
+yard
+yards
+yarn
+yarns
+ye
+yeah
+year
+years
+yell
+yelled
+yelling
+yellow
+yells
+yep
+yer
+yes
+yesterday
+yet
+yield
+yielded
+yielding
+yields
+yo
+you
+young
+younger
+youngest
+youngster
+youngsters
+your
+yours
+yourself
+youth
+youths
+zero
+zeros
+zone
+zones
diff --git a/soloraidar.py b/soloraidar.py
index e47e7a1f..6495dfc3 100644
--- a/soloraidar.py
+++ b/soloraidar.py
@@ -1,8 +1,14 @@
__author__ = "Toeofdoom"
+import time
import sys
+import os.path
from evtcparser import *
from analyser import *
+from enum import IntEnum
+import json
+from zipfile import ZipFile
+import argparse
def is_basic_value(node):
try:
@@ -12,7 +18,7 @@ def is_basic_value(node):
return True
def flatten(root):
- nodes = dict((key, dict(node)) for key,node in root)
+ nodes = dict((key, dict(node)) for key,node in root.items())
stack = list(nodes.keys())
for node_name in stack:
node = nodes[node_name]
@@ -23,28 +29,78 @@ def flatten(root):
stack.append(full_child_name)
except TypeError:
pass
+ except ValueError:
+ pass
return nodes
-def print_node(key, node):
- basic_values = filter(lambda key:is_basic_value(key[1]), node.items())
- print("{0}: {1}".format(key, ", ".join(
- ["{0}:{1}".format(name, value) for name,value in basic_values])))
+def format_value(value):
+ if isinstance(value, IntEnum):
+ return value.name
+ else:
+ return value
+
+def print_node(key, node, f=None):
+ basic_values = list(filter(lambda key:is_basic_value(key[1]), node.items()))
+ if basic_values:
+ output_string = "{0}: {1}".format(key, ", ".join(
+ ["{0}:{1}".format(name, format_value(value)) for name,value in basic_values]))
+ print(output_string, file=f)
def main():
- filename = sys.argv[1]
-
- print("Parsing {0}".format(filename))
- with open(sys.argv[1], mode='rb') as file:
- e = parser.Encounter(file)
- a = analyser.Analyser(e)
- metrics = a.compute_all_metrics()
- flattened = flatten(metrics)
- for key in flattened:
- print_node(key, flattened[key])
- #for skill in e.skills:
- # print("Skill \"{0}\"".format(skill.name))
- #for event in e.events:
- #print("Skill \"{0}\"".format(event.src_agent))
+
+
+ zipfile = None
+
+ argparser = argparse.ArgumentParser(description='Process some integers.')
+ argparser.add_argument('filenames', metavar='N', type=str, nargs='+',
+ help='the files to load')
+ argparser.add_argument('-s', dest='silent', action='store_true',
+ help='silent mode, no output dump')
+ argparser.add_argument('--no-json', dest='json', action='store_false',
+ help='disable json output')
+
+ args = argparser.parse_args()
+ start_all = time.clock()
+ print("Parsing {0}".format(args.filenames))
+ for filename in args.filenames:
+ print("Loading {0}".format(filename))
+ with open(filename, mode='rb') as file:
+
+ if filename.endswith('.evtc.zip'):
+ zipfile = ZipFile(file)
+ contents = zipfile.infolist()
+ if len(contents) == 1:
+ file = zipfile.open(contents[0].filename)
+ else:
+ print('Only single-file ZIP archives are allowed', file=sys.stderr)
+ sys.exit(1)
+
+ start = time.clock()
+ e = parser.Encounter(file)
+ print("Parsing took {0} seconds".format(time.clock() - start))
+ print("Evtc version {0}".format(e.version))
+
+ start = time.clock()
+ a = analyser.Analyser(e)
+ print("Analyser took {0} seconds".format(time.clock() - start))
+
+ start = time.clock()
+ with open('Output/'+os.path.basename(filename)+'.txt','w') as output_file:
+ flattened = flatten(a.data)
+ for key in sorted(flattened.keys()):
+ if not args.silent:
+ print_node(key, flattened[key])
+ print_node(key, flattened[key], output_file)
+ print("Completed parsing {0} - Success: {1}".format(
+ list(a.data['Category']['boss']['Boss'].keys())[0],
+ a.data['Category']['encounter']['success']))
+ print("Readable dump took {0} seconds".format(time.clock() - start))
+
+ if "--no-json" not in sys.argv:
+ start = time.clock()
+ print(json.dumps(a.data), file=open('output.json','w'))
+ print("JSon dump took {0} seconds".format(time.clock() - start))
+ print("Analysing all took {0} seconds".format(time.clock() - start_all))
if __name__ == "__main__":
main()