Разработка системы анализа стилистики синтаксических конструкций научных текстов на английском языке

Задача автоматизированного анализа стиля англоязычных текстов. Описание алгоритмов и библиотек для автоматизированного анализа текстов на английском языке. Реализация системы для анализа синтаксического стиля научных текстов на английском языке.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 27.08.2018
Размер файла 665,8 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

conj:amod

conj (conjunct) - координирующая связь между двумя элементами, выраженная, например, с помощью «and», «or».

amod (adjectival modifier) - любая прилагательная фраза, которая служит для изменения значения существительного.

Кроме описанных выше маркеров, производился подсчет статистики по некоторым маркерам, выделенным профессиональными лингвистами. В частности, производился поиск следующих конструкций:

1. Длина предложений (выступает как индикатор синтаксической сложности предложений).

2. Порядок слов в предложении:

2.1. Использование прилагательных перед существительными, которых они описывают.

2.2. Главные субъект в начале предложения.

3. Th-конструкции (this, that, these those).

4. Wh-конструкции (who, where, what, why. when).

5. Вопросительные предложения: прямые и косвенные.

Как было сказано выше в процессе разработки было поставлено множество гипотез об использовании различных синтаксических конструкций в научных текстах на английском языке. Очевидно, что не все из поставленных гипотез были бы подтверждены. Для первоначального отсеивания неподходящих гипотез использовался коэффициент вариации. Коэффициент вариации показывает насколько выборка выровнена или по-другому: насколько велик разброс значений случайной величины. И таким образом, несмотря на то, что в процессе исследования ставилось много гипотез, данный коэффициент позволял отсеивать самые неудачные из них.

После расчета коэффициента вариации для каждой из эмпирически собранных выборки данных, были определены только самые удачные гипотезы. Важно отметить, что для каждой из анализируемых тематик был определен свой набор значимых метрик. Как оказалось в ходе разработки, даже работы, принадлежащие к одной области научных знаний (например, к социальным наукам), но к разным дисциплинам (например, экономика и политология), имеют разные не только значения эталонных диапазонов по собираемым метрикам, но и сам набор метрик отличается.

Для определения наиболее вероятных значений параметров по каждой из выбранных статистических характеристик, можно воспользоваться методом квантилей. С помощью двустороннего квантиля уровня можно задать интервал, в который анализируемая случайная величина попадает с заданной вероятностью. Для примера рассмотрим статистику, собранную для случайной величины «синтаксическая сложность предложения». Данная случайная величина показывает среднюю сложность предложений, используемую в тексте. Синтаксическая сложность предложения является числовым выражением глубины (высоты) синтаксического дерева, полученного после разбора предложения. Вариационный ряд для непрерывной случайной величины «средняя синтаксическая сложность» представлен в таблице 3.3. Ширина интервала была рассчитана следующим образом.

Формула для нахождения количества интервалов (N - размер выборки):

Формула для нахождения ширины интервала (ymin и ymax - минимальное и максимальное значения случайной величины):

Таблица 3.3

Интервальный вариационный ряд

Границы интервала

Середина интервала

Частота наблюдения

Накопленная частота

Относительная частота

1

[2,240; 2,318)

2,279

1

1

0,007463

2

[2,318; 2,396)

2,357

5

6

0,037313

3

[2,396; 2,474)

2,435

13

19

0,097015

4

[2,474; 2,552)

2,513

45

64

0,335821

5

[2,552; 2,630)

2,591

33

97

0,246269

6

[2,630; 2,708)

2,669

19

116

0,141791

7

[2,708; 2,786)

2,747

13

129

0,097015

8

[2,786; 2,864)

2,825

1

130

0,007463

9

[2,864; 2,942)

2,903

2

132

0,014925

10

[2,942; 3,020)

2,981

1

133

0,007463

11

[3,020; 3,098)

3,059

0

133

0

12

[3,098; 3,17]

3,134

1

134

0,007463

Сумма

134

1

Визуализация относительных частот попадания случайной величины в заданный интервал в виде гистограммы выборки представлено на рисунке 3.1.

Рисунок 3.1 Гистограмма выборки

Далее необходимо построить функцию распределения. Диаграмма накопленных частот является аналогом (эмпирическим) интегральной функции распределения. Построенная диаграмма представлена на рисунке 3.2.

Рисунок 3.2 Диаграмма накопленных частот

Рассчитаем квантили Q1/20 и Q19/20. Интерпретацию полученных данных приведем после расчетов. Квантили для интервального ряда будут рассчитываться следующим образом:

Полученные результаты означают, что 5% выборки имеют среднюю синтаксическую сложность предложений менее 2,4002 и 5% выборки со значением средней сложности более 2,7758.

Посчитанные результаты можно отобразить на гистограмме распределения случайной величины (рисунок 3.3).

Рисунок 3.3 Квантили на гистограмме

Таким образом, на основе собранных эмпирических данных были определены допустимые диапазоны по каждому маркеру.

3.3 Разработка клиентской части приложения

Клиентское приложение выполнено в соответствии со спроектированной архитектурой и является тонким клиентом, который представлен браузером. Клиентская часть приложения, запускаемая в браузере, разработана с использованием Vue.js - JavaScript фрейморка с открытым кодом, который используется для построения пользовательского интерфейса. За счет низкого порога вхождения Vue позволяет быстро создавать универсальные и производительные приложения, которые достаточно просто поддерживать и тестировать. С помощью фреймворка Vue можно разделить веб-страницу на переиспользуемые компоненты (что ускоряет разработку), каждый из которых будет иметь свой собственный HTML код, CCS и JavaScript, необходимый для рендеринга этого компонента.

Архитектура клиентского приложения выполнена в соответствии с архитектурным паттерном MVVM (Model, View, ViewModel). Модель (Model) содержит данные и бизнес-логику, Представление (View) отвечает за пользовательский интерфейс, а Модель Представления обеспечивает связь между моделью и представлением через привязку данных (data binding).

Разработанный пользовательский интерфейс представлен на рисунке 3.4.

Рисунок 3.4 Главное окно личного кабинета

В процессе реализации клиентской части приложения были разработаны интерфейсы для рядового пользователя и для администратора системы. Администратор имеет следующие дополнительные возможности:

1. Загрузка новых эталонных документов по заданной тематике.

2. Запуск проверки всего корпуса эталонных документов по заданной тематике.

3. Визуализация в виде графиков собранной статистики для работ по заданной тематике.

4. Просмотр списка правил, отражающих эталонный синтаксических стиль работ по заданной тематике.

5. Редактирование эталонных диапазонов, используемых в правилах при проверке синтаксического стиля работ, добавление новых правил.

Интерфейс для загрузки эталонных работ по заданной тематике представлен на рисунке 3.5.

Рисунок 3.5 Загрузка эталонных работ

Редактирование стилевых правил в кабинете администратора представлено на рисунке 3.6.

Рисунок 3.6 Кабинет администратора (редактирование правил)

Программный код клиентской части приложения представлен в Приложении Б.

3.4 Тестирование разработанной системы

После разработки клиентской и серверной частей приложения для каждой из частей были написаны автоматизированные тесты.

Для тестирования серверного приложения были написаны Unit тесты. Были использованы следующие библиотеки для тестирования: JUnit, Spring Test. Одним из ключевых преимуществ использования фремворка Spring является внедрение зависимостей (dependency injection), что значительно упрощает тестирование. Это происходит за счет инверсии зависимостей и отказа от явного создания объектов, реализующих бизнес-логику.

Пример теста, проверяющего работу конечной точки (ресурса) представлен ниже (импорты опущены для увеличения читаемости). Данный тест проверяет работоспособность ресурса, отвечающего за авторизацию пользователей. Полный набор Unit-тестов для проверки работы серверной части представлен в Приложении В.

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

@AutoConfigureWebTestClient

public class LoginResourceTests {

@Autowired

private WebTestClient webClient;

@Test

public void loginTest() {

webClient.post()

.uri("/api/login")

.body(BodyInserts.fromObject(new LoginDto()

.setUserName("User-test")))

.exchange()

.expectStatus().isOk()

.expectBody().json("{\"status\": \"ok\"}");

}

}

Для тестирования клиентского приложения были написаны Unit тесты с использованием фреймворка Jasmine. Ниже приведен пример unit-теста, написанного для клиентского приложения. Представленный тест проверяет наличие необходимых функций в компоненте, а также валидирует установку поля login после примонтирования экземпляра. Полный набор тестов представлен в Приложении Г.

import Vue from 'vue'

import SyntaxyMain from 'SyntaxyMain.vue'

describe('SyntaxyMain', () => {

it('has an upload file function', () => {

expect(typeof SyntaxyMain.uploadFile).toBe('function')

})

it('sets the correct default user login', () => {

expect(typeof SyntaxyMain.data).toBe('function')

const defaultData = SyntaxyMain.data()

expect(defaultData.login).toBe('User1')

})

it('correctly sets the user login when created', () => {

const vm = new Vue(SyntaxyMain).$mount()

expect(vm.login).toBe('User-test')

})

})

Заключение

В ходе данной работы была разработана система для автоматизированной проверки стиля синтаксических конструкций научных текстов на английском языке. В процессе разработки были решены следующие задачи:

1. Проведен аналитический обзор существующих программных решений для автоматизированного анализа стиля английских текстов, выявлена необходимость разработки системы для анализа стиля синтаксических конструкций научных текстов на английском языке.

2. Описаны существующие средства (фреймворки) для осуществления синтаксического разбора предложения, выбран наиболее подходящий вариант для реализации системы (клиент-серверное веб-приложение).

3. Поставлены и проверены гипотезы о значимости некоторых синтаксических конструкций при анализе синтаксического стиля текста.

4. Произведено моделирование разрабатываемой системы.

5. Разработано необходимое API для работы системы.

6. Разработана серверная и клиентская части веб-приложения, позволяющего производить анализ стиля научных текстов на английском языке с точки зрения используемых синтаксических конструкций.

7. Разработана система автоматизированных unit-тестов и произведено тестирование разработанной системы.

Таким образом, была разработана система, которая позволяет производить анализ стиля синтаксических конструкций научных текстов на английском языке. Планируется использовать данную систему для обучения студентов хорошему синтаксическому стилю научных текстов на английском языке. Также планируется произвести работы по расширению функциональности разработанного веб-приложения. В частности, планируется добавить визуализацию результатов проверки работы в графическом виде для всех пользователей (сейчас такая функциональность доступна только администратору), а также улучшить систему стилевых рекомендаций путем.

Библиографический список

1. Payette J., Hirst G. An Intelligent Computer-Assistant for Stylistic Instruction. Springer. 1992. pp. 87-102.

2. DocBridge Delta // Visual Document Comparison & Quality Control. URL: https://www.compart.com/en/docbridge-delta/ (дата обращения: 07.05.2018).

3. After the Deadline. Spell, Style, and Grammar Checker. URL: www.afterthedeadline.com/ (дата обращения: 07.05.2018).

4. Jurafsky D., Martin J. H. Speech and language processing. 2017. p. 499.

5. Ellis, J.M. Linguistics, Literature, and the Concept of Style. Word, Vol. 26. 1970. pp. 65-78.

6. Paper Rater. URL: https://www.paperrater.com/ (дата обращения: 07.05.2018).

7. Online Text Correction. URL: www.onlinecorrection.com/ (дата обращения: 07.05.2018).

8. LanguageTool. Style and Grammar Checker. URL: https://languagetool.org/ (дата обращения: 07.05.2018).

9. Scribens. Free, Powerful English Grammar Checker. URL: https://www.scribens.com/ (дата обращения: 07.05.2018).

10. Корпусы - научно-исследовательская группа «Разработка программного обеспечения для проведения корпусных исследований английского языка» // НИУ ВШЭ - Пермь. URL: https://perm.hse.ru/bi/sfcr/corpora (дата обращения: 07.05.2018).

11. Lynch T., Anderson K. Grammar for Academic Writing. English Language Teaching Centre University of Edinburgh. 2013. 90 с.

12. Siepmann D., Gallagher J.D., Hannay M., Mackenzie J.L. Writing in English: A Guide for Advanced Learners. 2011. 479 с.

13. Ивченко Г., Медведев Ю. Математическая статистика. Либроком. 2014. 353 с.

14. Marneffe M-C., Manning C.D. Stanford typed dependencies manual. 2008. 20 c.

15. Docker - Build, Ship, and Run Any App, Anywhere. URL: https://www.docker.com/ (дата обращения: 07.05.2018).

Приложения

Приложение А Код серверной части приложения

package com.syntaxy.syntaxen;

import com.syntaxy.syntaxen.domain.SentenceParsingArrayResult;

import com.syntaxy.syntaxen.domain.ParseWordTreeNode;

import com.syntaxy.syntaxen.service.SyntaxNetService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.CommandLineRunner;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Arrays;

import java.util.List;

@SpringBootApplication

public class SyntaxEnApplication {

@Autowired

SyntaxNetService syntaxNetService;

public static void main(String[] args) {

SpringApplication.run(SyntaxEnApplication.class, args);

}

public void run(String... args) throws Exception {

List<SentenceParsingArrayResult> parsingArrayFrom = syntaxNetService.getParsingArrayFrom(Arrays.asList(

"The connections between Irish politicians and the private sector are the subject of constant speculation, particularly in the post Celtic Tiger period.",

"The connections between Irish politicians and the private sector are the subject of constant speculation, particularly in the post Celtic Tiger period.")

);

List<ParseWordTreeNode> parsingTreeFrom = syntaxNetService.getParsingTreeFrom(Arrays.asList(

"The connections between Irish politicians and the private sector are the subject of constant speculation, particularly in the post Celtic Tiger period.",

"The connections between Irish politicians and the private sector are the subject of constant speculation, particularly in the post Celtic Tiger period.")

);

int a = 0;

}

}

package com.syntaxy.syntaxen.web.rest;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.multipart.MultipartFile;

@RestController

public class FileResource {

@RequestMapping(value = "/upload-file", method = RequestMethod.POST)

public void handleFileUpload(@RequestParam("file") MultipartFile file) {

int a = 0;

}

}

package com.syntaxy.syntaxen.service;

import com.syntaxy.syntaxen.domain.SentenceParsingArrayResult;

import com.syntaxy.syntaxen.domain.ParseWordTreeNode;

import java.util.List;

public interface SyntaxNetService {

List<SentenceParsingArrayResult> getParsingArrayFrom(List<String> sentences);

List<ParseWordTreeNode> getParsingTreeFrom(List<String> sentences);

}

package com.syntaxy.syntaxen.service.impl;

import com.syntaxy.syntaxen.domain.SentenceParsingArrayResult;

import com.syntaxy.syntaxen.domain.ParseWordTreeNode;

import com.syntaxy.syntaxen.service.SyntaxNetService;

import org.springframework.core.ParameterizedTypeReference;

import org.springframework.http.HttpEntity;

import org.springframework.http.HttpMethod;

import org.springframework.http.ResponseEntity;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import java.util.List;

@Service

public class SyntaxNetServiceImpl implements SyntaxNetService {

@Override

public List<SentenceParsingArrayResult> getParsingArrayFrom(List<String> sentences) {

RestTemplate template = new RestTemplate();

HttpEntity requestEntity = new HttpEntity<>(

new RequestPayload().setStrings(sentences).setTree(false));

ResponseEntity<List<SentenceParsingArrayResult>> parsingResponse =

template.exchange("http://localhost:9000/api/v1/query", HttpMethod.POST,

requestEntity, new ParameterizedTypeReference<List<SentenceParsingArrayResult>>() {

});

List<SentenceParsingArrayResult> result = parsingResponse.getBody();

return result;

}

@Override

public List<ParseWordTreeNode> getParsingTreeFrom(List<String> sentences) {

RestTemplate template = new RestTemplate();

HttpEntity requestEntity = new HttpEntity<>(

new RequestPayload().setStrings(sentences).setTree(true));

ResponseEntity<List<ParseWordTreeNode>> parsingResponse =

template.exchange("http://localhost:9000/api/v1/query", HttpMethod.POST,

requestEntity, new ParameterizedTypeReference<List<ParseWordTreeNode>>() {

});

List<ParseWordTreeNode> result = parsingResponse.getBody();

return result;

}

static class RequestPayload {

private List<String> strings;

private boolean tree;

public List<String> getStrings() {

return strings;

}

public RequestPayload setStrings(List<String> strings) {

this.strings = strings;

return this;

}

public boolean getTree() {

return tree;

}

public RequestPayload setTree(boolean tree) {

this.tree = tree;

return this;

}

}

}

import java.io.IOException;

import java.text.MessageFormat;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class TagsFrequencyCheck {

public static final String SUBJECT_TAG = "nsubj";

public static final String CONJ_TAG = "conj";

public static final String COMPOUND_TAG = "compound"; // phone<-book // put->up

public static final String ACL_TAG = "acl";

public static final String ADVCL_TAG = "advcl";

public static final String ADVMOD_TAG = "advmod";

public static final String AMOD_TAG = "amod";

public static final String APPOS_TAG = "appos";

public static final String AUX_TAG = "aux";

public static final String CASE_TAG = "case";

public static final String CC_TAG = "cc";

public static final String CCOMP_TAG = "ccomp";

public static final String CLF_TAG = "clf";

public static final String COP_TAG = "cop";

public static final String CSUBJ_TAG = "csubj";

public static final String DET_TAG = "det";

public static final String DISCOURSE_TAG = "discourse";

public static final String DISLOCATED_TAG = "dislocated";

public static final String EXPL_TAG = "expl";

public static final String FIXED_TAG = "fixed";

public static final String FLAT_TAG = "flat";

public static final String GOESWITH_TAG = "goeswith";

public static final String IOBJ_TAG = "iobj";

public static final String LIST_TAG = "list";

public static final String MARK_TAG = "mark";

public static final String NMOD_TAG = "nmod";

public static final String NUMMOD_TAG = "nummod";

public static final String OBJ_TAG = "obj";

public static final String OBL_TAG = "obl";

public static final String ORPHAN_TAG = "orphan";

public static final String PARARAXIS_TAG = "parataxis";

public static final String PUNCT_TAG = "punct";

public static final String REPARANDUM_TAG = "reparandum";

public static final String VOCATIVE_TAG = "vocative";

public static final String XCOMP_TAG = "xcomp";

private List<ParseWordTreeNode> text;

private String paperId;

private int totalWordsCount;

private Map<String, Integer> statistics = new HashMap<>();

private List<Integer> maxSentenceDepth = new ArrayList<>();

public TagsFrequencyCheck(List<ParseWordTreeNode> text, String paperId) {

this.text = text;

this.paperId = paperId;

for (ParseWordTreeNode sentenceRoot: text) {

TraverseContext context = new TraverseContext();

context.currentDepth = 1;

context.parent = sentenceRoot;

countSubjects(sentenceRoot, context);

maxSentenceDepth.add(context.maxDepth);

}

}

public List<TagFrequencyCheck> makeAllAvailableTags() {

List<TagFrequencyCheck> result = new ArrayList<>();

statistics.forEach((tag, stats) -> {

TagFrequencyCheck c = makeTagCheck(tag);

result.add(c);

});

return result;

}

public TagFrequencyCheck makeTagCheck(String tag) {

TagFrequencyCheck check = new TagFrequencyCheck();

Integer totalCount = statistics.getOrDefault(tag, 0);

check.setPaperId(paperId);

check.setTotalCount(totalCount);

check.setAverage((double) totalCount / totalWordsCount);

check.setTagName(tag);

return check;

}

private void countSubjects(ParseWordTreeNode node, TraverseContext context) {

totalWordsCount += 1;

countTag(node.getDep());

countTag(node.getPosTag());

String parentDep;

if (context.parent == null) {

parentDep = "-";

} else {

parentDep = context.parent.getDep();

}

String parentPlusCurrentDep = parentDep + ":" + node.getDep();

countTag(parentPlusCurrentDep);

switch (node.getWord().toLowerCase()) {

case "that":

case "these":

case "those":

case "this":

countTag("ThatThose");

break;

}

if (node.getContains() == null) {

context.maxDepth = Math.max(context.currentDepth, context.maxDepth);

context.currentDepth -= 1;

return;

}

ParseWordTreeNode oldParent = context.parent;

context.currentDepth += 1;

context.parent = node;

for (ParseWordTreeNode child: node.getContains()) {

countSubjects(child, context);

}

context.parent = oldParent;

}

private void countTag(String dep) {

if (dep != null) {

statistics.put(dep, statistics.getOrDefault(dep, 0) + 1);

}

}

public List<ParseWordTreeNode> getText() {

return text;

}

public double getAvgMaxDepth() {

return maxSentenceDepth.stream().mapToInt(x -> x).average().orElse(0);

}

public Result performStudentPaperAnalysis(String configJson) {

Config config = Config.fromJson(configJson);

List<Message> messages = new ArrayList<>();

for (IdealValue idealValue: config.idealValues) {

Integer stats = statistics.get(idealValue.tag);

if (stats == null) {

continue;

}

if (idealValue.max != null && stats > idealValue.max) {

messages.add(new Message(

idealValue.tag,

MessageFormat.format(

"max value is {0}, your value is {1}",

idealValue.max, stats)

));

}

if (idealValue.min != null && stats < idealValue.min) {

messages.add(new Message(

idealValue.tag,

MessageFormat.format(

"min value is {0}, your value is {1}",

idealValue.min, stats)

));

}

double avg = stats.doubleValue() / totalWordsCount;

if (idealValue.avgMax != null && avg > idealValue.avgMax) {

messages.add(new Message(

idealValue.tag,

MessageFormat.format(

"avg max value is {0}, your value is {1}",

idealValue.avgMax, avg)

));

}

if (idealValue.avgMin != null && avg < idealValue.avgMin) {

messages.add(new Message(

idealValue.tag,

MessageFormat.format(

"avg min value is {0}, your value is {1}",

idealValue.avgMin, avg)

));

}

}

return new Result(messages);

}

private static class TraverseContext {

private int currentDepth;

private int maxDepth;

private ParseWordTreeNode parent;

}

public static class Result {

private final List<Message> messages;

public Result(List<Message> messages) {

this.messages = messages;

}

public List<Message> getMessages() {

return messages;

}

}

public static class Message {

private final String tag;

private final String message;

public Message(String tag, String message) {

this.tag = tag;

this.message = message;

}

public String getTag() {

return tag;

}

public String getMessage() {

return message;

}

}

public static class Config {

private List<IdealValue> idealValues = new ArrayList<>();

public static Config fromJson(String configJson) {

if (configJson == null) {

configJson = "{}";

}

ObjectMapper mapper = new ObjectMapper();

Config config;

try {

config = mapper.readValue(configJson, Config.class);

} catch (IOException e) {

throw new RuntimeException(e);

}

return config;

}

public String toJson() {

ObjectMapper mapper = new ObjectMapper();

try {

return mapper.writeValueAsString(this);

} catch (IOException e) {

throw new RuntimeException(e);

}

}

public List<IdealValue> getIdealValues() {

return idealValues;

}

public Config setIdealValues(List<IdealValue> idealValues) {

this.idealValues = idealValues;

return this;

}

}

private static class IdealValue {

private String label;

private String tag;

private Double min;

private Double max;

private Double avgMin;

private Double avgMax;

public String getLabel() {

return label;

}

public IdealValue setLabel(String label) {

this.label = label;

return this;

}

public String getTag() {

return tag;

}

public IdealValue setTag(String tag) {

this.tag = tag;

return this;

}

public Double getMin() {

return min;

}

public IdealValue setMin(Double min) {

this.min = min;

return this;

}

public Double getMax() {

return max;

}

public IdealValue setMax(Double max) {

this.max = max;

return this;

}

public Double getAvgMin() {

return avgMin;

}

public IdealValue setAvgMin(Double avgMin) {

this.avgMin = avgMin;

return this;

}

public Double getAvgMax() {

return avgMax;

}

public IdealValue setAvgMax(Double avgMax) {

this.avgMax = avgMax;

return this;

}

}

}

Приложение Б Код клиентской части приложения

<template>

<div id="hello">

<div id="toolbar">

<div id="logo">

<p id="logo-p">

<router-link to="SyntaxyMain">Syntaxy</router-link>

</p>

</div>

<div id="top-menu">

<button class="top-btn" v-on:click="logout">Выйти</button>

</div>

</div>

<div id="admin-upload" v-if="admin">

<p>

<input placeholder="Politology" type="text" v-model="labelText">

<button v-on:click="adminCheck">Проверить файлы</button>

<button v-on:click="showStats">Статистика</button>

</p>

<uploader ref="uploaderprof"

:options="optionsprof" class="uploader">

<uploader-unsupport/>

<uploader-drop>

<p>Перетащите файлы сюда, чтобы загрузить тексты для проверки</p>

<uploader-btn>Выберите файл</uploader-btn>

</uploader-drop>

<uploader-list/>

</uploader>

</div>

<div id="paper-uploader">

<uploader ref="uploader"

:options="options" class="uploader">

<uploader-unsupport/>

<uploader-drop>

<p>Перетащите файлы сюда, чтобы загрузить тексты для проверки</p>

<uploader-btn>Выберите файл</uploader-btn>

</uploader-drop>

<uploader-list/>

</uploader>

</div>

<div>

<vuetable ref="vuetable"

api-url="api/v1/papers"

:fields=fields

data-path="content"

initialPage=0

pagination-path="pagination"

@vuetable:row-clicked="rowClicked"

@vuetable:pagination-data="onPaginationData"

/>

<vuetable-pagination ref="pagination"/>

</div>

</div>

</template>

<script>

import Vuetable from 'vuetable-2/src/components/Vuetable'

import VuetablePagination from 'vuetable-2/src/components/VuetablePagination'

import axios from 'axios';

import moment from 'moment';

export default {

name: 'app',

props: {

msg: String

},

components: {

Vuetable,

VuetablePagination

},

data() {

return {

currentUser: null,

optionsprof: {

// https://github.com/simple-uploader/Uploader/tree/develop/samples/Node.js

target: '/api/v1/upload-prof-paper',

testChunks: false,

query: (file, chunck, isTest) => {

return {'label': this.labelText};

}

},

options: {

// https://github.com/simple-uploader/Uploader/tree/develop/samples/Node.js

target: '/api/v1/upload-paper',

testChunks: false

},

attrs: {},

fields: [

{

name: 'name',

title: 'Название'

},

{

name: 'uploadDate',

title: 'Дата загрузки',

callback: 'formatDate'

}

],

paperLabels: {

politology: 'politology',

},

admin: false,

labelText: "",

adminFiles: null,

}

},

watch: {

labelText: function (val) {

if (val) {

this.optionsprof.target = 'api/v1/upload-prof-paper?label=' + val;

}

},

},

methods: {

transform: function(data) {

const transformed = {};

transformed.pagination = {

total: data.totalElements,

per_page: data.pageable.pageSize,

current_page: data.number + 1,

last_page: data.totalPages,

next_page_url: '/api/v1/papers?page=' + data.number + 1,

prev_page_url: '/api/v1/papers?page=' + data.number - 1,

from: data.from,

to: data.to

};

transformed.content = data.content;

return transformed

},

onPaginationData (paginationData) {

console.log(paginationData);

this.$refs.pagination.setPaginationData(paginationData);

},

rowClicked: function(dataitem, event) {

this.$router.push({name: 'PaperDetail', params: {id: dataitem.id}})

},

logout: function (event) {

event.preventDefault();

axios.post(`/api/v1/auth/logout`)

.then(response => {

this.$router.push({name: 'Login'});

});

},

getPaperResults: function (paperId) {

axios.post(`/api/v1/paper-results`, {

'paperId': paperId

}).then(response => {

console.log(response);

});

},

formatDate: function (value) {

moment.locale('ru');

return moment(value).calendar();

},

onFileChange(e) {

const files = e.target.files || e.dataTransfer.files;

if (!files.length) {

this.adminFiles = null;

return;

}

this.adminFiles = e.target.files;

},

sendAdminFile: function () {

console.log(this.adminFiles);

console.log(this.labelText);

if (this.adminFiles && this.labelText) {

const that = this;

for (const file of this.adminFiles) {

axios.post(`/api/v1/upload-prof-paper`, {

file: file,

label: that.labelText

}).then(response => {

console.log(response);

});

}

}

},

adminCheck: function () {

if (this.labelText) {

const that = this;

axios.post(`/api/v1/prof-paper-results`, {

label: that.labelText,

tag: 'nsubj'

}).then(response => {

console.log(response);

});

}

},

showStats: function () {

this.$router.push({name: 'Chart', params: {label: this.labelText}});

},

},

mounted: function () {

axios.get('/api/v1/users/me')

.then(response => {

this.currentUser = response.data;

this.admin = this.currentUser.login === "admin";

})

.catch(e => {

const response = e.response;

if (response && response.data && response.data && response.data.key === 'user.not-authenticated') {

this.$router.push({name: 'Login'});

} else {

this.$notice({

type: 'error',

text: e,

});

this.$router.push({name: 'Login'});

}

});

this.$refs.vuetable.loadData();

const uploader = this.$refs.uploader.uploader;

const that = this;

uploader.on('fileSuccess', function (rootFile, file, message) {

that.$refs.vuetable.refresh();

console.log(message);

const paperId = JSON.parse(message)["id"]

that.getPaperResults(paperId);

});

}

}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->

<style scoped>

.uploader {

/*width: 880px;*/

padding: 15px;

font-size: 12px;

box-shadow: 0 0 10px rgba(0, 0, 0,.4);

}

.uploader.uploader-btn {

margin-right: 4px;

}

.uploader.uploader-list {

max-height: 440px;

overflow: auto;

overflow-x: hidden;

overflow-y: auto;

}

.uploader-drop {

border: 1px dashed #21d4fd;

}

.ui.blue.table {

border-top:.2em solid #21d4fd;

}

#paper-uploader {

margin: 65px 12% 18px 12%;

}

#top-menu {

margin: 10px 20px 10px 10px;

display: flex;

flex-direction: row;

justify-content: center;

}

.top-btn {

display: inline-block;

position: relative;

padding: 4px 8px;

font-size: 90%;

line-height: 1.4;

color: #666;

border: 1px solid #9a9a9a;

cursor: pointer;

border-radius: 2px;

background: #f5f5f5;

outline: none;

}

#toolbar {

z-index: 100;

/*background-color: #2962FF;*/

/*background-color: #25292f;*/

background: linear-gradient(to left, #21d4fd, #b721ff);

display: flex;

flex-direction: row;

position: fixed;

left: 0;

top: 0;

margin-bottom: 4px;

width: 100%;

justify-content: space-between;

}

#logo {

margin: 10px 10px 10px 20px;

display: flex;

flex-direction: row;

justify-content: center;

}

#logo-p {

font-size: 20px;

font-weight: bold;

color: #fff;

}

#admin-upload {

margin: 65px 12% 18px 12%;

}

#admin-btn {

margin-top: 10px;

}

</style>

Приложение В Тесты серверной части приложения

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

@AutoConfigureWebTestClient

public class LoginResourceTests {

@Autowired

private WebTestClient webClient;

@Test

public void loginTest() {

webClient.post()

.uri("/api/login")

.body(BodyInserts.fromObject(new LoginDto()

.setUserName("User-test")))

.exchange()

.expectStatus().isOk()

.expectBody().json("{\"status\": \"ok\"}");

}

}

Приложение Г Тесты клиентской части приложения

import Vue from 'vue'

import SyntaxyMain from 'SyntaxyMain.vue'

describe('SyntaxyMain', () => {

it('has an upload file function', () => {

expect(typeof SyntaxyMain.uploadFile).toBe('function')

})

it('sets the correct default user login', () => {

expect(typeof SyntaxyMain.data).toBe('function')

const defaultData = SyntaxyMain.data()

expect(defaultData.login).toBe('User1')

})

it('correctly sets the user login when created', () => {

const vm = new Vue(SyntaxyMain).$mount()

expect(vm.login).toBe('User-test')

})

})

Размещено на Allbest.ru


Подобные документы

  • Инструменты анализа академического стиля английского языка. Проектирование архитектуры портала для анализа и оценки стиля научных публикаций на основе методов корпусной лингвистики. Моделирование жизненного цикла системы и взаимодействия её компонентов.

    дипломная работа [2,4 M], добавлен 27.08.2017

  • Понятие семантики; обзор и анализ существующих средств семантического разбора естественно-языковых текстов. Разработка алгоритма работы системы на основе семантического анализа, его реализация на языке программирования; проектирование интерфейса системы.

    дипломная работа [1,7 M], добавлен 18.03.2012

  • Морфологические анализаторы (морфологизаторы) на различных языках программирования. Анализ методов и технологий автоматической обработки ЕЯ-текстов. Разработка модуля графематического анализа и создания таблицы лексем. Программная реализация классов.

    дипломная работа [3,0 M], добавлен 06.03.2012

  • Разработка программного продукта для психолингвистического анализа текстов. Предметная область, основные требования. Анализ рабочих процессов отдела рекламно-выставочной и издательской деятельности. Оценка эффективности проекта и стоимости владения.

    дипломная работа [3,1 M], добавлен 12.10.2015

  • Разработка алгоритма автоматического создания отзывов на русском языке с использованием лексико-синтаксических шаблонов. Процесс создания текста при помощи цепей Маркова. Принцип работы Томита-парсера. Применение автоматических генераторов текстов.

    курсовая работа [150,6 K], добавлен 27.09.2016

  • Особенности системы вопросно-ответного поиска информации. Выбор таксономии семантических тэгов. Ознакомление с символьными шаблонами вопросов на английском языке из системы OpenEphyra. Правила работы тривиального модуля анализа вопросов на русском языке.

    реферат [776,7 K], добавлен 16.03.2014

  • Состав и принцип работы аппаратуры. Выбор параметров корреляционного анализа и Фурье-анализа. Разработка и применение алгоритма корреляционного анализа. Реализация алгоритма Фурье-анализа на языке С++ и алгоритма корреляционного анализа на языке С#.

    дипломная работа [4,6 M], добавлен 30.11.2016

  • Составление транслятора на языке С для перевода кода программы из языка Pascal в код программы на языке Cи. Распознавание и перевод конструкций: for, type, function, integer. Вешняя спецификация, описание, структура, текст программы; распечатка текстов.

    курсовая работа [287,8 K], добавлен 24.06.2011

  • Понятие синтаксического анализа. Программный продукт для обработки данных строкового типа. Построение сканера текстов с использованием утилиты flex, синтаксического анализатора с помощью утилиты bison. Грамматика языка программирования обработки строк.

    курсовая работа [261,7 K], добавлен 29.10.2012

  • Разработка системы автоматизированного анализа сложных объектов образовательной системы. Построение диаграмм последовательности, кооперации, классов, состояний, компонентов, а также развертывания. Представление сгенерированных кодов клиента и сервера.

    курсовая работа [501,1 K], добавлен 23.06.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.