|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Приложение 1 Справочник по языку JScript Язык JScript — это разработанный Microsoft интерпретируемый объектно-ориентированный язык сценариев, который первоначально предназначался для создания динамических HTML-страниц. Отметим, что JScript не является урезанной версией какого-либо другого языка программирования, хотя по синтаксису он похож на языки Java и С. В этом приложении мы кратко рассмотрим те возможности и свойства JScript, которые могут потребоваться при составлении сценариев, выполняемых с помощью WSH, не затрагивая при этом вопросы, связанные с составлением сценариев для HTML-страниц. Строки кода и комментарии В конце каждого оператора JScript нужно ставить точку с запятой. Например: var theSum =0, і; sum[0] = 0; При этом один оператор может располагаться на нескольких строках, например: var theSum = 0, і; sum[0] = 0; Комментарии в JScript могут быть двух видов. Для комментария, который занимает не более одной строки, можно использовать символы //. Например: //Этот комментарий занимает всю строку theSum=1; //А этот часть строки Если же в текст сценария необходимо внести комментарий, расположенный на нескольких строках, то текст такого комментария нужно помещать внутри блока /*…*/. Например: /* Это комментарий на нескольких строках */ Переменные В сценариях JScript, как и в любом другом языке программирования, можно использовать переменные, обращаясь к ним по имени. При этом переменные могут быть как глобальными (доступными из любого места сценария), так и локальными (область действия ограничивается функцией, в которой они определены). Хорошим тоном считается предварительное объявление используемых переменных с помощью ключевого слова var, хотя это является обязательным условием только для локальных переменных, определенных в функциях. Пример объявления переменной имеет вид: var MyVariable; При объявлении тип переменной явным образом не указывается (как это делается, например, в языках С или Pascal). Определенный тип переменной присваивается только тогда, когда в нее записывается какое-либо значение. Язык JScript является регистро-зависимым, т.е. имена MyVariableи myvariableпредставляют разные переменные. Кроме этого, при выборе имен переменных следует придерживаться следующих правил: ? имя переменной должно начинаться с буквы или с символов " _", " $" и может состоять только из букв, цифр, а также символов " _", " $"; ? имя переменной не должно совпадать с зарезервированными ключевыми словами языка JScript. Список ключевых слов JScript приведен в табл. П1.1. Таблица П1.1. Зарезервированные ключевые слова JScript break default false new true case delete finally null try catch do for return typeof class else function super var const enum if switch void continue export import this while debugger extends in throw with Значения переменным в JScript присваиваются с помощью оператора присваивания "=". Например: var MyVariable; MyVariable = "Привет!"; Здесь мы объявили переменную MyVariableи записали в нее текстовую строку. Однако далее в любом месте сценария мы можем присвоить переменной MyVariableчисловое значение (при этом тип переменной изменится), например: MyVariable = 10; Кроме этого, переменной можно присвоить специальное значение null: MyVariable = null; В этом случае переменной MyVariableне назначается никакого определенного типа (пустой тип). Такое присваивание применяется в тех случаях, когда необходимо объявить переменную и проинициализировать ее, не присваивая этой переменной никакого определенного типа и значения. Типы данных В JScript поддерживаются шесть типов данных, главными из которых являются числа, строки, объекты и логические данные. Оставшиеся два типа — это null (пустой тип) и undefined (неопределенный тип). Числа В сценариях JScript числа могут использоваться в различных форматах. ? Целые числа в диапазоне от -999 999 999 999 999 до 999 999 999 999 999. Кроме обычного десятичного, целые числа могут записываться в восьмеричном (префикс "0" и цифры 0–7) или в шестнадцатиричном (префикс "0х", цифры 0–9, символы "А", "В", "С", "D", "Е" и "F') виде. Например, восьмеричное число 0377 и шестнадцатеричное 0xFF равны десятичному 255. ? Вещественные числа, которые могут быть записаны как с плавающей точкой (например, -10.567), так и в научной нотации (например, 10567Е-3, что равно 10.567 ("число 10 567 умножить на 10 в степени -3")). Значения вещественных переменных и констант должны лежать в диапазоне от -Number.MAX_VALUE до Number.MAX_VALUE, где параметр Number.MAX_VALUE является специальным числовым значением, которое равно наибольшему вещественному числу, с которым может работать JScript (Number.MAX_VALUE приблизительно равно 1.79Е+308). Кроме Number.MAX_VALUE в JScript имеются еще несколько специальных числовых значений. ? NaN (Not a Number) — так называемое "нечисло", которое не соответствует никакому числу (это значение генерируется в тех случаях, когда результат выполнения операции не может быть представлен в виде числа, например, при преобразовании строки "1s2" к числовому типу). ? Положительная бесконечность Number.POSITIVE_INFINITY (число, которое больше, чем Number.MAX_VALUE). ? Отрицательная бесконечность Number.NEGATIVE_INFINITY (число, которое меньше, чем -Number.MAX_VALUE). ? Самое близкое число к нулю Number.MIN_VALUE (примерно равно 2.22Е-308). Все числа, большие -Number.MIN_VALUE, но меньшие Number.MIN_VALUE, считаются равными нулю. Текстовые строки Текстовые строки — это последовательность символов, заключенных в одинарные или двойные кавычки, например: "Привет!" 'Большой привет!' 'И тогда он крикнул "Берегись!"' Строка может иметь нулевую длину (пустая строка): MyVariable = ""; В JScript можно также использовать специальные комбинации символов, с помощью которых в строки включаются некоторые неотображаемые символы или символы, имеющие специальное значение. Каждая из этих комбинаций (escape-последовательностей) начинается с символа обратной косой черты " \" (табл. П1.2). Таблица П1.2. Специальные комбинации символов
Объекты В JScript под объектом понимается совокупность свойств и методов. Метод — это внутренняя функция объекта, свойство — это одно значение какого-либо типа или несколько таких значений (в виде массива или объекта), хранящихся внутри объекта. Поддерживаются три вида объектов: ? встроенные (внутренние) объекты; ? объекты, создаваемые программистом в сценарии; ? внешние объекты (например, объекты WSH). Более подробно объекты будут рассмотрены ниже. Логические данные Логические данные предназначены для выполнения операций сравнения, а также для использования в условных операторах. При этом логические данные имеют только два значения: true(истина) и false(ложь). Отметим, что в JScript эти значения никак не соотносятся с числами 1 и 0. Null (пустой тип) и undefined (неопределенный тип) Если переменная была объявлена с помощью ключевого слова var, но ей еще ни разу не присваивалось значение, она имеет неопределенный тип (undefined): var MyVariable; После выполнения этой строки переменная MyVariableимеет тип undefined. Как уже отмечалось выше, если теперь присвоить переменной значение null, то эта переменная будет типа null(пустой тип): MyVariable = null; Преобразование типов данных Одной из особенностей языка JScript является то, что если в выражениях встречаются переменные разных типов, то автоматически происходит преобразование всех числовых данных в строковое представление. Например, следующие логические выражения будут равны true: "100" == 100 false == 0 (здесь "==" означает оператор сравнения). Для преобразования строк в числа нужно применять две специальные функции: parseInt(преобразование к целому числу) и parseFloat(преобразование к числу с плавающей запятой). Например, после выполнения следующих строк: var s=""; s=(parseInt("3")-2)+"3"; значением переменной sбудет строка " 13". Операторы В JScript поддерживаются операторы различных типов, которые похожи на операторы языка С. Унарные операторы Унарными называются операторы, которые применяются к одному операнду (табл. П1.3). Таблица П1.3. Унарные операторы
Бинарные операторы Бинарными называются операторы, которые соединяют два операнда (табл. П1.4). Таблица П1.4. Бинарные операторы
Операторы побитовых логических операций и сдвига Эти операторы позволяют производить над числовыми переменными побитовые операции, описанные в табл. П1.5. Таблица П1.5. Операторы побитовых логических операций и сдвига
Замечание Операторы присваивания В JScript, как и в языке С, для изменения содержимого переменных можно комбинировать оператор присваивания "=" с другими операторами (табл. П1.6). Таблица П1.6. Комбинации оператора присваивания и других операторов
Операторы отношения Операторы отношения используются для сравнения значений нескольких переменных. Эти операторы, описанные в табл. П1.7, могут возвращать только логические значения trueили false. Таблица П1.7. Операторы отношения
Также в условных операторах применяются логические операторы (табл. П1.8). Таблица П1.8. Логические операторы
Условные операторы В JScript поддерживается условный оператор if…else. Общий вид этого оператора показан ниже: if (условие) выражение_1 [else выражение_2] При выполнении оператора if…elseоценивается логическое условие, заданное в круглых скобках после ключевого слова if. Если в результате оценки условия получилось значение true, то выполняется первое выражение. В противном случае выполняется второе выражение (если оно присутствует). Оператор if…elseможет быть вложенным. Заметим, что если в первом или втором выражении нужно расположить несколько операторов, то их следует выделить фигурными скобками: if (х == 5) { if (у == 6) z = 17; } else z = 20; В JScript также существует специальный тип условного оператора, который называется оператором " ?:". В общем виде он записывается так: условие ? выражение_1 : выражение_2 При вычислении оператора " ?:" вначале оценивается условие, расположенное в левой части. Если оно равно true, то выполняется первое выражение, в противном случае — второе. Например: hours += (theHour >=12) ? " РМ" : " AM"; Операторы циклов Microsoft JScript поддерживает несколько типов циклов: цикл for, цикл for…in, цикл while, цикл do…while. Рассмотрим каждый из них подробнее. Цикл for В общем случае оператор цикла for имеет три раздела (инициализация, условие и итерация) и записывается следующим образом: for ([инициализация;] [условие;] [итерация]){ тело цикла } В разделе инициализации обычно выполняется присваивание начальных значений переменным цикла. Здесь можно объявлять новые переменные с помощью ключевого слова var. Во втором разделе задается условие выхода из цикла. Это условие оценивается каждый раз при прохождении цикла. Если в результате такой оценки получается логическое значение true, то начинают выполняться строки из тела цикла; в противном случае происходит выход из цикла. В том случае, когда условие было ложным с самого начала (при первой проверке), цикл не будет выполнен ни разу. Раздел итерации применяется для изменения значений переменных цикла (например, увеличения или уменьшения значения счетчика цикла). Пример использования цикла forприведен в листинге П1.1. Листинг П1.1. Пример использования цикла for var howFar = 11; // Верхний предел для счетчика цикла var sum = new Array(howFar); //Массив из 11 элементов, индексы от 0 до 10 var theSum = 0; sum[0] = 0; //Цикл выполнится 10 раз for(var icount = 1; icount < howFar; icount++) { theSum += icount; sum [icount] = theSum; } var newSum = 0; //Цикл не выполнится ни разу for(var icount = 1; icount > howFar; icount++) { newSum += icount; } var sum = 0; //Бесконечный цикл for(var icount = 1; icount > 0; icount++) { sum += icount; } Цикл for…in Оператор цикла for…inпредназначен для просмотра всех свойств объекта. Для каждого свойства указанный цикл выполняет операторы, содержащиеся в теле цикла: for (переменная in объект) { тело цикла } Цикл for…inможно использовать для вывода на экран всех свойств объекта в одном цикле: function objectDisplay(obj) { var displayLine; for (var prop in obj) { displayLine=obj.name+"."+prop+"="+obj[prop]; WScript.Echo(displayLine) } WScript.Echo("--------------"); } Цикл while Цикл whileпохож на цикл for. В нем также условие выхода из цикла проверяется перед выполнением итерации, однако в цикле while, в отличие от for, нет встроенного счетчика и выражения, его изменяющего. Оператор whileзаписывается в следующем виде: while (условие) { тело цикла } Пример использования цикла whileприведен в листинге П1.2. Листинг П1.2. Пример использования цикла while var theMoments = ""; var theCount = 42; // Начальное значение счетчика цикла while (theCount >= 1) { if (theCount > 1) { theMoments = "До взрыва осталось " + theCount + " сек!"; } else { theMoments = "Осталась секунда!"; } theCount--; // Уменьшаем значение счетчика } theMoments = "ВЗРЫВ!"; Цикл do…while Этот цикл является примером цикла с пост-условием и записывается в следующем виде: do { тело цикла } while (условие); В этом случае цикл выполняется до тех пор, пока проверяемое после ключевого слова whileусловие не станет ложным ( false). Так как условие проверяется уже после прохождения тела цикла, то операторы внутри цикла do…whileвыполнятся по крайней мере один раз. Пример использования цикла do…whileприведен в листинге П1.3. Листинг П1.3. Пример использования цикла do…while var howFar = 11; // Верхний предел для счетчика цикла var sum = new Array(howFar); //Массив из 11 элементов, индексы от 0 до 10 var theSum = 0; sum[0] = 0; var icount - 1; //Цикл выполнится 10 раз do { theSum += icount; sum [icount] = theSum; icount++; } while (icount < howFar); Внутри цикла любого вида можно применять два специальных оператора: breakи continue. Оператор break С помощью оператора breakможно прервать выполнение цикла в любом месте; управление при этом передастся на оператор, следующий сразу за циклом. var i = 0; while (i < 100) { if (i == 50) break; i++; } i++; // Значение i станет равным 51 Оператор continue Оператор continueпрерывает текущую итерацию цикла и начинает новую. В различных видах циклов этот оператор производит следующие действия: ? в циклах whileи do…whileпроверяется условие цикла и если оно равно true, то вновь выполняется тело цикла; ? в цикле forизменяется значение счетчика в разделе итерации, проверяется условие цикла и если оно равно true, то тело цикла выполняется вновь; ? в цикле for…inпеременная цикла переходит к следующему полю объекта, и тело цикла выполняется вновь. Пример использования оператора continue: var s = "", i=0; while (i < 10) { i++; // Пропускаем число 5 if (i==5) { continue; } } s += i; Прочие операторы Рассмотрим еще несколько часто применяемых операторов (см. табл. П1.9). Таблица П1.9. Прочие операторы
С помощью оператора " ," можно, например, в разделе итерации цикла forизменять значение сразу нескольких переменных: var i, j; j = 10; for (i = 0; i<=10; i++, j--) { … } Обработка исключительных ситуаций Во время выполнения сценария могут возникать различные исключительные ситуации (например, деление на ноль или попытка открыть несуществующий файл), которые приводят к ошибкам времени выполнения — при этом на экран выводится диалоговое окно с сообщением об ошибке и выполнение сценария прекращается. Существует возможность написать код сценария таким образом, чтобы исключительные ситуации не приводили к завершению работы, а обрабатывались бы внутри сценария. Для осуществления подобной обработки исключительных ситуаций в JScript необходимо использовать конструкцию try…catch. Синтаксис следующий: try Защищенный блок catch (except) Блок обработки исключительных ситуаций После ключевого слова tryздесь записываются те операторы, при выполнении которых потенциально может возникнуть ошибка. В качестве параметра exceptнадо использовать любое имя переменной (предварительно объявлять эту переменную не нужно). Если в защищенном блоке не возникло ошибки, то значение этой переменной будет равно нулю; в случае же возникновения исключительной ситуации управление сразу передается в блок catch, при этом переменная exceptкак экземпляр объекта Errorбудет содержать два свойства: error— числовой код возникшей ошибки и description— краткое описание ошибки. В качестве примера приведем часть сценария, в которой происходит обработка исключительных ситуаций при подключении сетевого диска: try { //Подключаем сетевой диск WshNetwork.MapNetworkDrive(Drive, NetPath); } catch (e) { //Обрабатываем возможные ошибки if (e != 0) { //Выводим сообщение об ошибке Mess="Ошибка при подключении диска " + Drive + " к " + NetPath+ "\nКод ошибки: "+е.number+"\nОписание: "+е.description; WshShell.Popup(Mess, 0, "Подключение сетевого диска", vbCritical); } } Порядок выполнения операторов В табл. П1.10 операторы языка JScript расположены по старшинству, т.е. в составных операторах первыми будут выполняться те из них, которые стоят в этой таблице выше. Если операторы расположены в одной строке таблицы, то они выполняются слева направо. Таблица П1.10. Порядок выполнения операторов
Функции Функции в JScript, как и в других алгоритмических языках, позволяют объединить несколько операций под одним именем. В случае необходимости функция может быть вызвана из любого места сценария. В сценариях JScript поддерживаются два вида функций: встроенные функции и функции пользователя, которые вы пишете сами. Встроенные функции В табл. П1.11 описаны встроенные функции языка JScript, которые в сценарии можно вызывать в любом месте без предварительного описания. Таблица П1.11. Встроенные функции
Функции пользователя Функции, определяемые пользователем, могут находиться в любом месте сценария и иметь произвольное число параметров (аргументов). Общий вид определения функции имеет вид: function Имя_функции([параметр1] [, параметр2] [... , параметрN]) { … Тело функции … [return значение;] } Ключевое слово returnпозволяет функции вернуть значение любого допустимого типа. Например, приведенная ниже функция MyFunctionвозвращает true, если оба ее аргумента меньше 10: function MyFunction(х,у) { if ((х<10) && (у<10)) return true else return false; } Встроенные объекты (классы) Как уже отмечалось в самом начале раздела, JScript является объектно-ориентированным языком, поэтому математические вычисления, работа со строками, датой и временем, а также такими структурами, как массивы и коллекции, осуществляются с помощью соответствующих встроенных объектов. В табл. П1.12 описаны некоторые объекты, которые могут быть полезны при создании сценариев с помощью WSH. Таблица П1.12. Некоторые встроенные объекты JScript
Для того чтобы в сценарии использовать встроенный объект, необходимо создать переменную, с помощью которой можно будет получить доступ к свойствам и методам этого объекта. Для создания большинства переменных такого вида применяется оператор newи специальная функция — конструктор нужного объекта. Название конструктора всегда совпадает с названием соответствующего встроенного объекта. Приведем пример создания объектов Dateи Array! var d; d = new Date(); var a; a = new Array(10); Отметим, что объекты string можно создавать, просто записывая в кавычках значение строки: var s; s = "Привет!"; Опишем объекты, приведенные в табл. П1.12, более подробно. Объект Array Новый объект встроенного класса Arrayможно создать с помощью оператора newследующими способами: ? new Array()— создание массива нулевой длины; ? new Array(N)— создание массива длины N; ? new Array(а0, a1, ..., aN)— создание массива длины N+1c элементами а0, a1, ..., aN. Например: var A1, А2, A3; A1 = new Array(); A2 = new Array(3); A3 = new Array(0, "Строка", 2.5); Нумерация элементов в массивах всегда начинается с нуля. После того как массив создан и проинициализирован, обращаться к его элементам можно с помощью обычного оператора индексации [], например: A3[1] = А3[0] + A3[2]; Длину массива, т.е. число содержащихся в нем элементов, можно узнать с помощью свойства lengthобъекта Array. Для того чтобы динамически изменить длину массива (уменьшить или увеличить), достаточно просто записать соответствующее значение в свойство length: var А; А = new Array(1,2,3,4,5); // Длина массива А равна 5 A.length = 3; // Теперь длина массива А равна 3 Некоторые наиболее часто используемые методы встроенного объекта Arrayописаны в табл. П1.13. Таблица П1.13. Методы объекта
Пример использования методов объекта Array приведен в листинге П1.4. Листинг П1.4. Пример использования методов объектаArray var A1, А2, A3; A1 = new Array(2); A2 = new Array(2,3,4,5); A1[0] = 0; A1[1] = 1; A3 = A2.concat(A1); // A3=(2,3,4,5,0,1) A3.sort(); // A3=(0,1,2,3,4,5) Объект Date Для создания нового объекта встроенного класса Dateиспользуется один из трех конструкторов. Конструктор первого вида позволяет создать объект, в котором хранится информация о текущих дате и времени: var d; d = new Date(); Здесь время задается по Гринвичу, т.е. с использованием времени (UCT — Universal Coordinated Time). Конструктор второго вида имеет единственный параметр: var d; d = new Date(nMilliseconds); Параметр nMillisecondsзадает дату в миллисекундах, считая от 1 января 1970 года. Конструктор третьего вида предназначен для раздельного задания компонентов даты и имеет следующий вид: var d; d = new Date(year, month, date [, hours [, min [, sec [, ms]]]]); Значения параметров последнего конструктора приведены в табл. П1.14. Таблица П1.14. Параметры конструктора
Наиболее часто используемые методы объекта Dateописаны в табл. П1.15. Таблица П1.15. Некоторые методы объекта
Пример использования методов объекта Dateприведен в листинге П1.5. Листинг П1.5. Пример использования методов объекта Date var d; var s = ""; d = new Date(); s = "Дата: " + d.getDate() + "." + d.getMonth() + "." + d.getYear(); s += "\n"; s += "Время: " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds(); После выполнения этих строк в переменной sбудут записаны текущие дата и время. Объект Enumerator С помощью объекта Enumeratorможно получить доступ к любому элементу коллекции (в VBScript для этого служит цикл For…Each). Коллекцией в языке JScript называется множество элементов, которое отличается от массива тем, что к элементам коллекции нельзя получить прямой доступ с помощью индексов — можно только перемешать указатель текущего элемента на самый первый или следующий относительно текущего элемент. Для создания нового объекта встроенного класса Enumeratorиспользуется конструктор следующего вида: var е; е = new Enumerator(collection); Здесь параметр Enumerator. Сами коллекции обычно являются свойствами других объектов. Методы объекта Enumeratorпредставлены в табл. П1.16 (свойств у этого объекта нет). Таблица П1.16. Методы объекта
Пример, поясняющий схему применения объекта Enumerator, приведен в листинге П1.6. Листинг П1.6. Пример использования Enumerator //Объявляем переменные var FSO, Folder, Files, s; //Создаем объект FileSystemObject FSOWScript.CreateObject("Scripting.FileSystemObject"); //Создаем объект Folder для корневого каталога диска С: Folder=FSO.GetFolder("С:\\")? //Создаем коллекцию файлов каталога "Мои документы" Files=new Enumerator(Folder.Files); //Цикл по всем файлам for (; !Files.atEnd(); Files.moveNext()) //Добавляем строку с именем файла s+=Files.item().Name+"\n"; //Выводим полученные строки на экран WScript.Echo(s); Объект Math Встроенный класс Mathприменяется для математических вычислений и содержит основные математические константы и функции. Замечание Свойства объекта Math(все они являются математическими константами) описаны в табл. П1.17. Таблица П1.17. Свойства объекта
Методы объекта Math(они являются стандартными математическими функциями) приведены в табл. П1.18. Таблица П1.18. Методы объекта
Приведем пример использования свойств и методов встроенного объекта Math: var x,y,z; х = 12; у = Math.sqrt(х); z = 2*Math.PI * Math.pow(у, x); Объект String Встроенный объект Stringпредназначен для выполнения различных операций над текстовыми строками. Обычно объекты класса Stringсоздаются просто с помощью записи в переменную текстового литерала: var s1, s2; s1 = "Это строка"; s2 = "Это тоже строка"; Также можно создавать такие объекты с помощью оператора new: var s1, s2; s1 = new String("Это строка"); s2 = new String("Это тоже строка"); Объект Stringимеет свойство length, в котором хранится длина строки. Некоторые методы объекта String, не связанные с тегами HTML, приведены в табл. П1.19. Таблица П1.19. Некоторые методы объекта
Приведем пример использования методов объекта String: var s1, s2, s3; s1 = "Первая строка"; s2 = "Вторая строка"; s1 = s1.toUpperCase(); s2 = s2.substr(0, 6); s1 = s1.slice(7); s3 = s2 + " " + s1; После выполнения этих строк значением переменной s3будет строка " Вторая строка". |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Главная | Контакты | Нашёл ошибку | Прислать материал | Добавить в избранное |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|