Groton Municipal Employees Federal Credit Union is a forward-thinking and growing credit union built upon more than 56 years of commitment and service to our members and our community. We believe in supporting organizations and activities devoted to improving our members' communities and their quality of life.
As a not-for-profit financial cooperative, we are owned by our members – the people that save and borrow through us. When you become a Groton Municipal Employees FCU member, you become an owner in an organization that is democratically governed by a board of directors with oversight by an appointed Supervisory Committee. They are unpaid volunteers who represent the interests of their fellow members.
We are committed to providing the financial resources you need to better manage your money and make informed financial choices.
Employees and elected or appointed officials of the Town or City of Groton, Connecticut (Police, fire, school board, teachers, etc.).
Employees and elected or appointed officials of the Town Montville, Connecticut (Police, fire, school board, teachers, etc.).
Employees of VNASC (Visiting Nurse Association) who work in the Town or City of Groton, CT. Note: in 1996 the Groton Public Health Nursing Service, Inc. merged with Waterford Public Health Nursing Service, Shoreline and the Stonington Visiting Nurse Association to form the VNASC.
Also included are spouses of persons who died while within the field of membership of this credit union, employees of this credit union, persons retired as pensioners or annuitants from the above employment, members of their immediate family or household, and organizations of such persons. Once a member always a member.
The Groton Municipal Employees Federal Credit Union was formed in 1956 by Raymond Bugbee and William Clinton Jr. The original Board of Directors were six members comprised of Bugbee, Clinton, Robert Falvey, John Ball, James Davis, Frank Kohl, and Burton Wilbur.
Since its inception, the Credit Union has been served by 75 different volunteers from the membership. When the Credit Union first opened, its total assets were $7,800.00. Assets now exceed $7,000,000.00. The original location of the Credit Union was 359 Thames Street in Groton. In 1966 the Credit Union moved to its Meridian Street location, but it was upstairs in City Hall rooms C-7 and C-8. In 1987, the Credit Union moved into the basement of the Municipal building. The Credit Union moved again in 2018 and is presently located at 44 Plaza Court, Groton, CT. On behalf of the entire membership, we would like to thank each and every volunteer, both past and present for their dedication and generosity in contributing to the growth and success of the Credit Union.


A beautiful and classic British army smock design that has become more and more scarce. The two we have are older versions with beautiful Lightning Zippers.
We have two in stock, both in great lightly used condition.
shoulder to shoulder (approx, raglan) 18"
shoulder to cuff (approx, raglan) 24"


text:
import BaseControl from './BaseControl'
let Snap = require('snapsvg');
let TimelineMax = require('TimelineMax');

export default class GraphControl extends BaseControl {
	/**
	 * 单例
	 */
	static _inst;

	static getInst() {
		GraphControl._inst = GraphControl._inst || new GraphControl();

		return GraphControl._inst;
	}

	/**
	 * 构造
	 */
	constructor() {
		super();
	}

	/**
	 * 析构
	 */
	destroy() {
		this.unbindEvent();
		if (this.animateObj) {
			this.animateObj.kill();
			this.animateObj = null;
		}
		GraphControl._inst = null;
	}

	/**
	 * 初始化事件
	 */
	init(app) {

		this.app = app;

		// 初始化svg界面
		var uid = 'svg' + this.uuid();
		this.container = this.app.$view.find('.parallel-container');
		this.container.html('<svg id="' + uid + '" style="width: 100%;height: 100%;" ></svg>');
		this.$svg = this.app.$view.find('#' + uid);
		this.svg = Snap('#' + uid);

		// svg绘制参数设置
		this.svgWidth = this.$svg.width();
		this.svgHeight = this.$svg.height();

		this.app.config.lineAX = this.app.config.initLeftratios[0] * this.svgWidth;
		this.app.config.lineBX = this.app.config.initLeftratios[1] * this.svgWidth;

		for (let i = 1; i < 6; i++) {
			this.app.config['y' + i] = Math.round((this.svgHeight / 6 * i + this.svgHeight / 15)*1000)/1000;
		}

		this.app.config.y0 = 0;

		this.transformPosition = {
			x: 0,
			y: 0
		};

		this.canvasBoundary = {
			minX: -this.svgWidth,
			minY: -this.svgHeight,
			maxX: this.svgWidth * 2,
			maxY: this.svgHeight * 2
		};

		this.pointGroupArr = [];

		this.parallelLineGroupArr = [];

		this.crossingLineArr = [];

		Snap.plugin(function(Snap, Element, Paper, glob) {
			var elproto = Element.prototype;
			elproto.toFront = function(target) {
				if (target) {
					this.appendTo(target);
					return this
				}
				this.appendTo(this.paper);
			};
			elproto.toBack = function(target) {
				if (target) {
					this.prependTo(target);
					return this
				}
				this.prependTo(this.paper);
			};

			elproto.setPosition = function(position, direct) {
				switch (this.type) {
					case 'circle':
						if (direct) {
							this.attr({
								'cx': position.x,
								'cy': position.y
							})
						} else {
							this.attr({
								'cx': '+=' + position.x,
								'cy': '+=' + position.y
							})
						}
						break;
					case 'line':
						if (direct) {
							this.attr({
								'x1': position.x1,
								'y1': position.y1,
								'x2': position.x2,
								'y2': position.y2
							});
						} else {
							this.attr({
								'x1': '+=' + position.x,
								'y1': '+=' + position.y,
								'x2': '+=' + position.x,
								'y2': '+=' + position.y
							});
						}
						break;

					default:
						if (direct) {
							this.attr({
								x: position.x,
								y: position.y
							})

						} else {
							this.attr({
								x: '+=' + position.x,
								y: '+=' + position.y
							})
						}
						break;
				}
			}

		});
		this.initFormula();
		this.drawBasic();
		this.bindEvent()
		return this;
	}

	/**
	 * 初始化公式面板
	 */
	initFormula() {
		this.$formulaContainer = this.app.$view.find(".ParallelLines_formula"); //公式面板,控制线段比例的显示隐藏
		/*
		 三条线时公式形式
		 */
		this.$littileFormula = this.app.$view.find(".formula_little:first");
		//第一项
		this.$littileF_rowTxt1 = this.$littileFormula.find(".rowTxt:first");
		this.$littileF_rowTxt1_member = this.$littileF_rowTxt1.find("i:first");
		this.$littileF_rowTxt1_denominator = this.$littileF_rowTxt1.find("i:last");
		//等号1
		this.$littileF_equal1 = this.$littileFormula.find(".equal:last");
		//第二项
		this.$littileF_rowTxt2 = this.$littileFormula.find(".rowTxt:last");
		this.$littileF_rowTxt2_member = this.$littileF_rowTxt2.find("i:first");
		this.$littileF_rowTxt2_denominator = this.$littileF_rowTxt2.find("i:last");
		//等号2
		this.$littileF_equal2 = this.$littileFormula.find(".equal:last");
		//比例值
		this.$littileF_verMid = this.$littileFormula.find(".verMid");

		/*
		 三条线以上时公式形式
		 */
		this.$manyFormula = this.app.$view.find(".formula_many:first");
		let rowTxts = this.$manyFormula.find(".rowTxt");
		//第一项
		this.$manyF_rowTxt1 = rowTxts.first();
		//第二项
		this.$manyF_rowTxt2 = rowTxts.eq(1);
		//第三项
		this.$manyF_rowTxt3 = rowTxts.last();

		/*
		 有线段等于0时显示
		 */
		this.$equalFormulas = this.app.$view.find(".formula_equal");

	}

	/**
	 * 生成id
	 * @return {[string]} [返回随机字符串]
	 */
	uuid() {
		let s = [],
			hexDigits = '0123456789abcdef';
		for (let i = 0; i < 10; i++) {
			s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
		}

		return s.join('');
	}

	/**
	 * 绘制基本界面
	 */
	drawBasic() {
		this.group = this.svg.g();

		// 相交线A
		let lineA = this.drawLine('crossingLine').addClass('lineA lineAX').data({
			type: 'X',
			classString: 'lineA'
		});

		let lineA2 = this.drawLine('crossingLine').addClass('lineA lineAX').data({
			type: 'X',
			classString: 'lineA'
		}).attr({
			'stroke-opacity': 0.001,
			'strokeWidth': this.app.config.unvisibleCrossingLineWidth
		});

		let textA = this.svg.text(0, 0, 'a').attr({
			fill: this.app.config.crossingLineColor
		}).addClass('textA');
		// 相交线B
		let lineB = this.drawLine('crossingLine').addClass('lineB lineBX').data({
			type: 'X',
			classString: 'lineB'
		});

		let lineB2 = this.drawLine('crossingLine').addClass('lineB lineBX').data({
			type: 'X',
			classString: 'lineB'
		}).attr({
			'stroke-opacity': 0.001,
			'strokeWidth': this.app.config.unvisibleCrossingLineWidth
		});

		let textB = this.svg.text(0, 0, 'b').attr({
			fill: this.app.config.crossingLineColor
		}).addClass('textB');

		// let baseSplit = this.svgHeight / 6;

		for (let i = 1; i < 6; i++) {

			let path = this.drawLine('parallelLine').addClass('parallelLine ' + this.app.config.allParallelLinesName[i - 1] + ' y' + i).data({
				type: 'Y',
				index: i
			});

			let path2 = this.drawLine('parallelLine').addClass('parallelLine ' + ' y' + i).data({
				type: 'Y',
				index: i
			}).attr({
				'stroke-opacity': 0.001,
				'strokeWidth': this.app.config.unvisibleParallelLineWidth
			});

			let text = this.svg.text(22 * this.app.config.fontSize / 24, -this.app.config.parallelLineWidth / 2 - this.app.config.textGap, this.app.config.allParallelLinesName[i - 1].split('')).attr({
				fill: this.app.config.parallelLineColor
			}).addClass('text_parallel_line y' + i);

			let parallelLineGroup = this.svg.g(path2, path, text).addClass('y' + i + 'Group ' + 'parallelLine' + i + 'Group');

			this.group.add(parallelLineGroup);
			this.parallelLineGroupArr.push(parallelLineGroup);
		}

		this.crossingLineArr.push(lineA);
		this.crossingLineArr.push(lineB);

		let lineAGroup = this.svg.g(lineA2, lineA).addClass('lineAXGroup');
		let lineBGroup = this.svg.g(lineB2, lineB).addClass('lineBXGroup');;

		this.group.add(lineAGroup, lineBGroup, textA, textB);

		this.drawPoints();

	}

	drag(position) {

		this.transformPosition.x += position.x;
		this.transformPosition.y += position.y;

		if (-this.transformPosition.x < this.canvasBoundary.minX) {
			this.transformPosition.x = -this.canvasBoundary.minX;
		} else if (this.svgWidth - this.transformPosition.x > this.canvasBoundary.maxX) {
			this.transformPosition.x = this.svgWidth - this.canvasBoundary.maxX;
		}

		if (-this.transformPosition.y < this.canvasBoundary.minY) {
			this.transformPosition.y = -this.canvasBoundary.minY;
		} else if (this.svgHeight - this.transformPosition.y > this.canvasBoundary.maxY) {
			this.transformPosition.y = this.svgHeight - this.canvasBoundary.maxY;
		}

		let transformString = 't ' + this.transformPosition.x + ' ' + this.transformPosition.y;

		this.group.transform(transformString);
	}

	controlTextShow({
		init = false,
		bool = '',
		i = -1
	} = {}) {
		if (bool === '') {
			if (init) {
				[-this.app.config.y1 / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX <=
					-this.app.config.y1 / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX, -this.app.config.y2 / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX <=
					-this.app.config.y2 / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX, -this.app.config.y3 / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX <=
					-this.app.config.y3 / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX, -this.app.config.y4 / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX <=
					-this.app.config.y4 / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX, -this.app.config.y5 / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX <=
					-this.app.config.y5 / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX
				].map((b, index) => {
					this.controlTextShow({
						bool: b,
						i: index
					});
				})
			} else {
				[-(this.app.config.y1 + this.app.data.y1) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX <=
					-(this.app.config.y1 + this.app.data.y1) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX, -(this.app.config.y2 + this.app.data.y2) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX <=
					-(this.app.config.y2 + this.app.data.y2) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX, -(this.app.config.y3 + this.app.data.y3) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX <=
					-(this.app.config.y3 + this.app.data.y3) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX, -(this.app.config.y4 + this.app.data.y4) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX <=
					-(this.app.config.y4 + this.app.data.y4) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX, -(this.app.config.y5 + this.app.data.y5) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX <=
					-(this.app.config.y5 + this.app.data.y5) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX
				].map((b, index) => {
					this.controlTextShow({
						bool: b,
						i: index
					});
				})
			}

		} else {

			if (!bool) {
				this.pointGroupArr[i][0].select('.text_point_left').removeClass('hidden_svg');
				this.pointGroupArr[i][0].select('.text_point_right').addClass('hidden_svg');

				this.pointGroupArr[i][1].select('.text_point_left').addClass('hidden_svg');
				this.pointGroupArr[i][1].select('.text_point_right').removeClass('hidden_svg');
			} else {
				this.pointGroupArr[i][0].select('.text_point_left').addClass('hidden_svg');
				this.pointGroupArr[i][0].select('.text_point_right').removeClass('hidden_svg');

				this.pointGroupArr[i][1].select('.text_point_left').removeClass('hidden_svg');
				this.pointGroupArr[i][1].select('.text_point_right').addClass('hidden_svg');

			}
		}
	}

	// 绘制相交线
	drawLine(type) {

		let startPoint = {
			x: this.canvasBoundary.minX,
			y: 0
		}
		let endPoint = {
			x: this.canvasBoundary.maxX,
			y: 0
		}

		return this.svg.line(startPoint.x, startPoint.y, endPoint.x, endPoint.y).attr({
			fill: 'none',
			stroke: this.app.config[type + 'Color'],
			strokeWidth: this.app.config[type + 'Width']
		});

	}

	drawPoints() {

		this.pointGroupArr = this.app.config.pointsNameArr.map((textArr, i) => {

			let unvisibleOutsideCircle1 = this.svg.circle(0, 0, this.app.config.unvisiblePointRadius).attr({
				fill: this.app.config.unvisiblePointFillColor,
				stroke: 'none'
			}).addClass('unvisibleCircle circle lineAX lineAPartY' + (i + 1)).data({
				line: 'lineA',
				type: 'rotate',
				row: 'y' + (i + 1)
			});

			let outsideCircle1 = this.svg.circle(0, 0, this.app.config.pointOutsideRadius).attr({
				fill: this.app.config.pointOutsideFillColor,
				stroke: 'none'
			}).addClass('outsideCircle circle lineAX lineAPartY' + (i + 1)).data({
				line: 'lineA',
				type: 'rotate',
				row: 'y' + (i + 1)
			});
			let circle1 = this.svg.circle(0, 0, this.app.config.pointRadius).attr({
				fill: this.app.config.pointFillColor,
				stroke: this.app.config.pointStrokeColor,
				strokeWidth: this.app.config.pointStrokeWidth
			}).addClass('circle lineAX lineAPartY' + (i + 1)).data({
				line: 'lineA',
				type: 'rotate',
				row: 'y' + (i + 1)
			});

			let leftText1 = this.svg.text(0 - this.app.config.pointRadius, 0 - this.app.config.pointRadius - this.app.config.textGap, textArr[0].split('')).attr({
				fill: this.app.config.pointTextColor
			}).addClass('text_point hidden_svg text_point_left lineAX lineAPartY' + (i + 1));

			leftText1.attr({
				x: +leftText1.attr('x') - leftText1.node.clientWidth * 5 / 4
			});

			let rightText1 = this.svg.text(0 + this.app.config.pointRadius, 0 - this.app.config.pointRadius - this.app.config.textGap, textArr[0].split('')).attr({
				fill: this.app.config.pointTextColor
			}).addClass('text_point hidden_svg text_point_right lineAX lineAPartY' + (i + 1));

			rightText1.attr({
				x: +rightText1.attr('x') + rightText1.node.clientWidth / 4
			});

			let group1 = this.svg.g(unvisibleOutsideCircle1, outsideCircle1, circle1, leftText1, rightText1).addClass('pointGroup lineAXGroup y' + (i + 1) + 'Group');

			let unvisibleOutsideCircle2 = this.svg.circle(0, 0, this.app.config.unvisiblePointRadius).attr({
				fill: this.app.config.unvisiblePointFillColor,
				stroke: 'none'
			}).addClass('unvisibleCircle circle lineBX lineBPartY' + (i + 1)).data({
				line: 'lineB',
				type: 'rotate',
				row: 'y' + (i + 1)
			});

			let outsideCircle2 = this.svg.circle(0, 0, this.app.config.pointOutsideRadius).attr({
				fill: this.app.config.pointOutsideFillColor,
				stroke: 'none'
			}).addClass('outsideCircle circle lineBX lineBPartY' + (i + 1)).data({
				line: 'lineB',
				type: 'rotate',
				row: 'y' + (i + 1)
			});
			let circle2 = this.svg.circle(0, 0, this.app.config.pointRadius).attr({
				fill: this.app.config.pointFillColor,
				stroke: this.app.config.pointStrokeColor,
				strokeWidth: this.app.config.pointStrokeWidth
			}).addClass('circle lineBX lineBPartY' + (i + 1)).data({
				line: 'lineB',
				type: 'rotate',
				row: 'y' + (i + 1)
			});

			let leftText2 = this.svg.text(0 - this.app.config.pointRadius, 0 - this.app.config.pointRadius - this.app.config.textGap, textArr[1].split('')).attr({
				fill: this.app.config.pointTextColor
			}).addClass('text_point hidden_svg text_point_left lineBX lineBPartY' + (i + 1));

			leftText2.attr({
				x: +leftText2.attr('x') - leftText2.node.clientWidth * 5 / 4
			});

			let rightText2 = this.svg.text(0 + this.app.config.pointRadius, 0 - this.app.config.pointRadius - this.app.config.textGap, textArr[1].split('')).attr({
				fill: this.app.config.pointTextColor
			}).addClass('text_point hidden_svg text_point_right lineBX lineBPartY' + (i + 1));

			rightText2.attr({
				x: +rightText2.attr('x') + rightText2.node.clientWidth / 4
			});
			let group2 = this.svg.g(unvisibleOutsideCircle2, outsideCircle2, circle2, leftText2, rightText2).addClass('pointGroup lineBXGroup y' + (i + 1) + 'Group');

			this.group.add(group1, group2);
			return [group1, group2]

		});

	}

	drawSegmentLines() {

		let length = this.pointGroupArr.length;
		for (let i = 1; i < length; i++) {
			let leftStartPoint = this.pointGroupArr[i - 1][0];
			let rightstartPoint = this.pointGroupArr[i - 1][1];
			let leftEndPoint = this.pointGroupArr[i][0];
			let rightEndPoint = this.pointGroupArr[i][1];
		}
	}

	drawByAngle(angle, classString, init) {
		let radian = Math.tan(angle);

		let pos;
		if (init) {
			pos = {
				y1: this.canvasBoundary.minY - this.app.config.lineGap,
				x1: -(this.canvasBoundary.minY - this.app.config.lineGap) / radian + this.app.config[classString + 'X'],
				y2: this.canvasBoundary.maxY + this.app.config.lineGap,
				x2: -(this.canvasBoundary.maxY + this.app.config.lineGap) / radian + this.app.config[classString + 'X']
			}

		} else {
			pos = {
				y1: this.canvasBoundary.minY - this.app.config.lineGap,
				x1: -(this.canvasBoundary.minY - this.app.config.lineGap) / radian + this.app.config[classString + 'X'] + this.app.data[classString + 'X'],
				y2: this.canvasBoundary.maxY + this.app.config.lineGap,
				x2: -(this.canvasBoundary.maxY + this.app.config.lineGap) / radian + this.app.config[classString + 'X'] + this.app.data[classString + 'X']
			}
		}

		[].slice.call(Snap.selectAll('.' + classString)).map(el => {
			el.setPosition(pos, true);
		})
	}

	drawByOffset({
		x = 0,
		y = 0
	} = {}, classString = null, direct = null) {
		let pos = {
			x,
			y
		};
		[].slice.call(Snap.selectAll('.' + classString)).map(el => {
			el.setPosition(pos, direct);
		})
	}

	drawParallelByOffset({
		x = 0,
		y = 0
	} = {}, index = null) {

		let group = Snap.select('.parallelLine' + index + 'Group');

		let originY = group.select('.parallelLine').attr('y1');
		let pos = {
			x,
			y: y - originY
		};

		[].slice.call(group.children()).map(el => {
			el.setPosition(pos);
		})
	}

	drawLineText(init = false, side, {
		x = 0,
		y = 0
	} = {}) {
		let pos1, pos2;
		let textA = Snap.select('.textA');
		let textB = Snap.select('.textB');
		if (init) {
			pos1 = {
				x: -(y + textA.node.clientHeight) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX - textA.node.clientWidth - this.app.config.textGap,
				y: +textA.node.clientHeight
			};
			pos2 = {
				x: -(y + textB.node.clientHeight) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.config.textGap,
				y: +textB.node.clientHeight
			};

			textA.data({
				x: textA.node.clientWidth,
				y: textA.node.clientHeight
			});
			textB.data({
				y: textB.node.clientHeight
			});

		} else {
			pos1 = {
				x: -(y + textA.data('y')) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX - textA.data('x') + this.app.data.lineAX - this.app.config.textGap,
				y: +textA.data('y')
			};
			pos2 = {
				x: -(y + textB.data('y')) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX + this.app.config.textGap,
				y: +textB.data('y')
			};

		}
		textA.setPosition(pos1, true);
		textB.setPosition(pos2, true);

		if (side) {
			textA.after(textB);
		}

	}

	drawPointByOffset({
		x = 0,
		y = 0
	} = {}, index = null, init = false) {

		let pos1, pos2;
		if (init) {

			pos1 = {
				x: -y / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX,
				y
			};
			pos2 = {
				x: -y / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX,
				y
			};

		} else {
			pos1 = {
				x: -y / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX,
				y
			};
			pos2 = {
				x: -y / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX,
				y
			};

		}

		let point1 = {
			x: +Snap.select('.circle.lineAPartY' + index).attr('cx'),
			y: +Snap.select('.circle.lineAPartY' + index).attr('cy')
		};
		let point2 = {
			x: +Snap.select('.circle.lineBPartY' + index).attr('cx'),
			y: +Snap.select('.circle.lineBPartY' + index).attr('cy')
		};

		let offset1 = {
			x: pos1.x - point1.x,
			y: pos1.y - point1.y
		};
		let offset2 = {
			x: pos2.x - point2.x,
			y: pos2.y - point2.y
		};

		this.drawByOffset(offset1, 'lineAPartY' + index);
		this.drawByOffset(offset2, 'lineBPartY' + index);
		this.controlTextShow({
			bool: pos1.x <= pos2.x,
			i: index - 1
		});
	}

	bringToFront(classString) {
		let group = Snap.selectAll('.' + classString);
		if (!classString || !group) {
			return
		}
		[].slice.call(group).map(el => {
			el.toFront(el.parent());
		})
	}

	controlSegments(init, side) {

		if (Snap.selectAll('.segmentGroup')) {
			Snap.selectAll('.segmentGroup').remove();
		}
		this.app.config.segmentShow.sort((a, b) => {

			if (init) {
				return this.app.config[a] > this.app.config[b]
			} else {
				return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
			}

		})

		let pointArr = this.app.config.segmentShow.map(key => {
			if (init) {
				return [{
					x: -(this.app.config[key]) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX,
					y: (this.app.config[key])
				}, {
					x: -(this.app.config[key]) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX,
					y: (this.app.config[key])
				}]
			} else {
				return [{
					x: -(this.app.config[key] + this.app.data[key]) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX,
					y: (this.app.config[key] + this.app.data[key])
				}, {
					x: -(this.app.config[key] + this.app.data[key]) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX,
					y: (this.app.config[key] + this.app.data[key])
				}]
			}
		});

		for (let i = 1; i < pointArr.length; i++) {
			let segment1 = this.svg.path(`M${pointArr[i-1][0].x} ${pointArr[i-1][0].y} L${pointArr[i][0].x} ${pointArr[i][0].y}`).attr({
				fill: 'none',
				stroke: this.app.config.segmentLineColors[i - 1][0],
				strokeWidth: this.app.config.crossingLineWidth
			}).addClass('segment');

			let segment2 = this.svg.path(`M${pointArr[i-1][1].x} ${pointArr[i-1][1].y} L${pointArr[i][1].x} ${pointArr[i][1].y}`).attr({
				fill: 'none',
				stroke: this.app.config.segmentLineColors[i - 1][1],
				strokeWidth: this.app.config.crossingLineWidth
			}).addClass('segment');

			let length1 = +segment1.getTotalLength();
			let textValue1 = Math.round(length1 * 100 / this.app.config.pixelToLength) / 100 < 0.01 ? '0' : '' + Math.round(length1 * 100 / this.app.config.pixelToLength) / 100;
			let center1 = (length1 * 100 / this.app.config.pixelToLength) / 100 < 0.01 ? {
				x: pointArr[i - 1][0].x,
				y: pointArr[i - 1][0].y
			} : segment1.getPointAtLength(length1 / 2);
			let text1 = null;

			let length2 = +segment2.getTotalLength();
			let textValue2 = Math.round(length2 * 100 / this.app.config.pixelToLength) / 100 < 0.01 ? '0' : '' + Math.round(length2 * 100 / this.app.config.pixelToLength) / 100;
			let center2 = (length2 * 100 / this.app.config.pixelToLength) / 100 < 0.01 ? {
				x: pointArr[i - 1][1].x,
				y: pointArr[i - 1][1].y
			} : segment2.getPointAtLength(length2 / 2);
			let text2 = null;

			let showDecide = center1.x <= center2.x;

			if (showDecide) {

				text1 = this.svg.text(center1.x, center1.y, textValue1).attr({
					fill: this.app.config.crossingLineColor
				}).addClass('segment text_segment');
				text1.attr({
					x: +text1.attr('x') - text1.node.clientWidth - this.app.config.textGap
				});
				text2 = this.svg.text(center2.x, center2.y, textValue2).attr({
					fill: this.app.config.crossingLineColor
				}).addClass('segment text_segment');

				text2.attr({
					x: +text2.attr('x') + this.app.config.textGap
				});

			} else {
				text1 = this.svg.text(center1.x, center1.y, textValue1).attr({
					fill: this.app.config.crossingLineColor
				}).addClass('segment text_segment');

				text1.attr({
					x: +text1.attr('x') + this.app.config.textGap
				});

				text2 = this.svg.text(center2.x, center2.y, textValue2).attr({
					fill: this.app.config.crossingLineColor
				}).addClass('segment text_segment');

				text2.attr({
					x: +text2.attr('x') - text2.node.clientWidth - this.app.config.textGap
				});
			}

			let group2 = this.svg.g(segment2, text2).addClass('segmentGroup');
			let group1 = this.svg.g(segment1, text1).addClass('segmentGroup');

			if (side) {
				this.group.add(group2, group1);
			} else {
				this.group.add(group1, group2);
			}

		}

		this.bringToFront('pointGroup');
		this.updateGraph('segmentRatioShow', this.app.config.segmentRatioShow)
		this.updateGraph('segmentLengthShow', this.app.config.segmentLengthShow)

	}

	animateControl(state) {

		switch (state) {
			case 0:
				if (this.animateObj) {
					this.animateObj.kill();

					this.animateObj = null;
				}
				break;
			case 1:
				if (this.animateObj) {
					this.animateObj.resume();
					return
				}
				this.animateObj = this.createAnimate();
				this.animateObj.play();
				break;
			case 2:
				if (this.animateObj) {
					this.animateObj.pause();
				}
				break;
			default:
				if (this.animateObj) {
					this.animateObj.kill();

					this.animateObj = null;
				}
				break;
		}

	}

	createAnimate() {
		this.app.config.segmentShow.sort((a, b) => {
			return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
		});
		let center;
		let length = this.app.config.segmentShow.length;
		let even = length % 2 === 0;
		if (even) {

			center = (this.app.config[this.app.config.segmentShow[length - 2]] + this.app.data[this.app.config.segmentShow[length - 2]] + this.app.config[this.app.config.segmentShow[1]] + this.app.data[this.app.config.segmentShow[1]]) / 2;

		} else {
			center = this.app.config[this.app.config.segmentShow[parseInt(length / 2)]] + this.app.data[this.app.config.segmentShow[parseInt(length / 2)]];
		}

		let moveArr = [];
		let t1 = new TimelineMax({
			onUpdate: function() {

				moveArr.map(obj => {
					this.app.data[obj.y] = obj.start - obj.diff;
					obj.diff = obj.start;
				})
			},
			onComplete: function() {
				t1.reverse()
			},
			onReverseComplete: function() {
				moveArr = null;
				this.app.data.animateShow = 0;
			},
			ease: Power0.easeNone,
			callbackScope: this,
			paused: true
		});

		let cover = this.app.config.segmentShow.reduce((a,b)=>{

			return Math.round((this.app.config[a] + this.app.data[a])*1000) === Math.round((this.app.config[b] + this.app.data[b])*1000)? b : null
		});

		for (let i = 0; i < length; i++) {

			let myObject = {
				y: this.app.config.segmentShow[i],
				diff: 0,
				start: 0,
				end: center - (this.app.config[this.app.config.segmentShow[i]] + this.app.data[this.app.config.segmentShow[i]])
			};
			if(cover){
				myObject.end = 0;
			}
			t1.to(myObject, Math.abs(myObject.end - myObject.start) / 50, {
				start: myObject.end
			}, 0);
			moveArr.push(myObject);
		}

		return t1;

	}

	checkOutsideCanvas({
		x = 0,
		y = 0,
		type = null,
		index = -1,
		classString = ''
	} = {}) {

		this.app.config.segmentShow.sort((a, b) => {
			return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
		});

		switch (type) {
			case 'X':

				let key1 = this.app.config.segmentShow[0];
				let key2 = this.app.config.segmentShow[this.app.config.segmentShow.length - 1];

				let x1 = -(this.app.config[key1] + this.app.data[key1]) / Math.tan(this.app.config[classString + 'Angle']) + this.app.config[classString + 'X'] + this.app.data[classString + 'X'] + x;
				let x2 = -(this.app.config[key2] + this.app.data[key2]) / Math.tan(this.app.config[classString + 'Angle']) + this.app.config[classString + 'X'] + this.app.data[classString + 'X'] + x;

				if (x1 < x2) {

					return x1 - this.app.config.pointRadius > this.canvasBoundary.minX && x2 + this.app.config.pointRadius < this.canvasBoundary.maxX
				} else {
					return x2 - this.app.config.pointRadius > this.canvasBoundary.minX && x1 + this.app.config.pointRadius < this.canvasBoundary.maxX
				}

				break;

			case 'Y':

				let pos1 = {
					x: -(this.app.config[index] + this.app.data[index] + y) / Math.tan(this.app.config.lineAAngle) + this.app.config.lineAX + this.app.data.lineAX,
					y: (this.app.config[index] + this.app.data[index] + y)
				}
				let pos2 = {
					x: -(this.app.config[index] + this.app.data[index] + y) / Math.tan(this.app.config.lineBAngle) + this.app.config.lineBX + this.app.data.lineBX,
					y: (this.app.config[index] + this.app.data[index] + y)
				};

				if ((pos1.y + this.app.config.pointRadius) < this.canvasBoundary.maxY && (pos1.y - this.app.config.pointRadius) > this.canvasBoundary.minY) {
					if (pos1.x < pos2.x) {
						return pos1.x - this.app.config.pointRadius > this.canvasBoundary.minX && pos2.x < this.canvasBoundary.maxX
					} else {
						return pos2.x - this.app.config.pointRadius > this.canvasBoundary.minX && pos1.x + this.app.config.pointRadius < this.canvasBoundary.maxX
					}
				}

				break;

			case 'rotate':

				let cover = this.app.config.segmentShow.reduce((a,b)=>{

					return Math.round((this.app.config[a] + this.app.data[a])*1000) === Math.round((this.app.config[b] + this.app.data[b])*1000)? b : null
				})

				if(cover){
					return
				}

				let last = this.app.config.segmentShow[this.app.config.segmentShow.length - 1];
				let first = this.app.config.segmentShow[0];
				if (index == first || index == last) {
					return (x - this.app.config.pointRadius) > this.canvasBoundary.minX && (x + this.app.config.pointRadius) < this.canvasBoundary.maxX
				}

				let movepoint = {
					x,
					y
				};

				let fitstPoint = {
					x: -(this.app.config[first] + this.app.data[first]) / Math.tan(this.app.config[classString + 'Angle']) + this.app.config[classString + 'X'] + this.app.data[classString + 'X'],
					y: (this.app.config[first] + this.app.data[first])
				};

				let k = -(movepoint.y - fitstPoint.y) / (movepoint.x - fitstPoint.x);
				let offset = movepoint.x - -(movepoint.y) / k;

				let checkX = -(this.app.config[last] + this.app.data[last]) / k + offset;

				return (checkX - this.app.config.pointRadius) > this.canvasBoundary.minX && (checkX + this.app.config.pointRadius) < this.canvasBoundary.maxX

				break;
			default:
				break;

		}
	}

	/**
	 * 旋转线段
	 * @param rotateData
	 */
	rotate(rotateData) {
		//        rotateData.x
		//        rotateData.y
		//        rotateData.row
		//        rotateData.path
		let segmentShow = this.app.config.segmentShow;
		//根据y值排序
		segmentShow.sort((a, b) => {
			return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
		})

		//算出圆心位置
		let center = {
				x: null,
				y: null
			},
			line = null,
			centerPointName = null,
			centerPoint = null;
		if (rotateData.row === segmentShow[0]) {
			line = segmentShow[segmentShow.length - 1];
		} else {
			line = segmentShow[0];
		}
		centerPointName = rotateData.path + "Part" + line.toUpperCase();
		centerPoint = Snap.selectAll("." + centerPointName)[1];
		center.x = centerPoint.attr("cx");
		center.y = centerPoint.attr("cy");
		let tan = -(rotateData.y - center.y) / (rotateData.x - center.x);
		// tan = Math.tan(75 * Math.PI / 180);
		let angle = Math.atan(tan);
		let offsetx = -(this.app.config[line] + this.app.data[line]) / Math.tan(this.app.data[rotateData.path + 'Angle']) + this.app.config[rotateData.path + 'X'] + this.app.data[rotateData.path + 'X'];
		this.app.config[rotateData.path + 'X'] = offsetx - -(this.app.config[line] + this.app.data[line]) / Math.tan(angle) - this.app.data[rotateData.path + 'X']
		this.app.data[rotateData.path + 'Angle'] = angle;
		//将点和线提升至最上层
		this.bringToFront(rotateData.path + 'XGroup')
			//更新点的位置
		this.app.data.y1 = 0;
		this.app.data.y2 = 0;
		this.app.data.y3 = 0;
		this.app.data.y4 = 0;
		this.app.data.y5 = 0;
	}

	/**
	 * 绑定svg点击事件
	 */
	bindEvent() {
		let that = this;
		let type = '';
		let target = null;
		let isDrag = false,
			eventData = {
				x: 0,
				y: 0
			};

		function mousedownEvent(e) {
			if (e.touches) {
				if (e.touches.length === 1) {
					e.preventDefault();
					e = e.changedTouches[0];
				} else {
					return
				}
			} else {
				e.preventDefault();
				if(e.which !== 1){
					return
				}
			}

			Snap.select('.selectedCircle') ? Snap.select('.selectedCircle').removeClass('selectedCircle') : null;
			if (that.app.data.animateShow) { //演示过程中不可点击
				return;
			}

			target = Snap(e.target);
			type = target.data('type');
			isDrag = false;
			eventData.startX = e.clientX;
			eventData.startY = e.clientY;
			if (type === 'rotate') {
				//选中该点
				let row = target.data('row');
				let targetLine = target.data('line');
				let pointName = targetLine + 'Part' + row.toUpperCase();
				target.parent().select('.outsideCircle').addClass('selectedCircle');
			}

			that.svg.mousemove(mousemoveEvent);
			that.svg.touchmove(mousemoveEvent);
			that.svg.touchcancel(mouseupEvent);
			that.svg.mouseup(mouseupEvent);
			that.svg.touchend(mouseupEvent);

		}

		function mousemoveEvent(e) {
			e.preventDefault();
			if (e.changedTouches) {
				e = e.changedTouches[0];
			}

			eventData.x = e.clientX - eventData.startX;
			eventData.y = e.clientY - eventData.startY;
			Snap.select('.parallelLineSelected') ? that.app.data.selectedParallelLine = '' : null;

			if ((Math.abs(eventData.x) > 5 || Math.abs(eventData.y) > 5)) {
				isDrag = true;
				that.app.data.reset = 1;
				if((eventData.x + eventData.startX - that.container.offset().left) > that.svgWidth || (eventData.x + eventData.startX - that.container.offset().left) < 0 ||
					(eventData.y + eventData.startY - that.container.offset().top) < 0 || (eventData.y + eventData.startY - that.container.offset().top) > that.svgHeight){
					mouseupEvent();
					return
				};

				switch (type) {
					case 'Y':
						let index = target.data('index');
						if (that.checkOutsideCanvas({
								y: eventData.y,
								index: 'y' + index,
								type
							})) {
							that.app.data['y' + index] = eventData.y;
						}
						break;
					case 'X':
						let classString = target.data('classString');
						if (that.checkOutsideCanvas({
								type,
								classString,
								x: eventData.x
							})) {

							that.app.data[classString + 'X'] = eventData.x;
						}
						break;
					case 'rotate':
						let row = target.data('row');
						let targetLine = target.data('line');
						if (that.checkOutsideCanvas({
								type,
								x: eventData.x + parseFloat(target.attr("cx")),
								y: parseFloat(target.attr("cy")),
								index: row,
								classString: targetLine
							})) {
							that.rotate({
								x: eventData.x + parseFloat(target.attr("cx")),
								y: parseFloat(target.attr("cy")),
								row: row,
								path: targetLine
							});
						}

						// that.app.data[]
						/*that.rotate({
						    x : eventData.x + parseFloat(target.attr("cx")) ,
						    y : parseFloat(target.attr("cy")),
						    row : row ,
						    path :targetLine
						});
						that.app.data[targetLine + 'X'] = eventData.x;*/
						break;
					default:
						that.drag(eventData);
						break;
				}
				eventData.startX = e.clientX;
				eventData.startY = e.clientY;
			}
		}

		function mouseupEvent(e) {
			/*
					 取消点的选中状态
					 */
			Snap.select('.selectedCircle') ? Snap.select('.selectedCircle').removeClass('selectedCircle') : null;
			if (!isDrag && target) {
				/*
				    更新平行线的选中状态
				     */
				let isSelectedBefore = target.hasClass('parallelLineSelected');
				if (!isSelectedBefore && target.hasClass('parallelLine') && that.app.data.showParallelLines.length > 3) {
					let index = target.data('index') - 1;
					that.app.data.selectedParallelLine = that.app.config.allParallelLinesName[index];
				} else {
					if (that.app.data.selectedParallelLine) {
						that.app.data.selectedParallelLine = '';
					}
				}
				that.app.data.reset = 1;
			}
			target = null;
			type = '';
			isDrag = false;
			that.svg.unmousemove();
			that.svg.untouchmove();
			that.svg.untouchcancel();
			that.svg.unmouseup();
			that.svg.untouchend();
		}

		this.svg.mousedown(mousedownEvent);
		this.svg.touchstart(mousedownEvent);

		this.container.on('mouseleave', e => {
			Snap.select('.selectedCircle') ? Snap.select('.selectedCircle').removeClass('selectedCircle') : null;
			this.svg.unmousemove();
			this.svg.untouchmove();
			this.svg.untouchcancel();
			this.svg.unmouseup();
			this.svg.untouchend();
		});

	}

	/**
	 * 解绑svg上的事件
	 */
	unbindEvent() {
		this.svg.unmousedown();
		this.svg.untouchstart();
		this.svg.unmousemove();
		this.svg.untouchmove();
		this.svg.unmouseup();
		this.svg.untouchcancel();
		this.svg.untouchend();
	}

	/**
	 * 更新图形
	 * @param item 数据项名称
	 * @param value 数据项新值
	 * @param oldValue 旧数据项
	 */
	updateGraph(item, value, oldValue) {
		switch (item) {
			case 'segmentLengthShow':
				{
					if (value === 1) {
						Snap.selectAll('.segmentGroup').forEach((seg) => seg[1].removeClass('hidden_svg'))
					} else {
						Snap.selectAll('.segmentGroup').forEach((seg) => seg[1].addClass('hidden_svg'))
					}
					break;
				}
			case 'segmentRatioShow':
				{
					if (value === 1) {
						Snap.selectAll('.segmentGroup').forEach((seg) => seg[0].removeClass('hidden_svg'))
					} else {
						Snap.selectAll('.segmentGroup').forEach((seg) => seg[0].addClass('hidden_svg'))
					}
					break;
				}
			case 'showParallelLines':
				{
					//更新线的显示隐藏
					let allParallelLinesName = this.app.config.allParallelLinesName;
					for (let i = 0; i < allParallelLinesName.length; i++) {
						let targetParallel = this.parallelLineGroupArr[i];
						let targetPoints = this.pointGroupArr[i];
						if (value.indexOf(allParallelLinesName[i]) !== -1) {
							targetParallel.removeClass('hidden_svg');
							targetPoints[0].removeClass('hidden_svg');
							targetPoints[1].removeClass('hidden_svg');
						} else {
							targetParallel.addClass('hidden_svg');
							targetPoints[0].addClass('hidden_svg');
							targetPoints[1].addClass('hidden_svg');
						}
					}

					//添加了数据,计算新线的位置
					if (oldValue && oldValue.length < value.length) {
						let newItem = null;
						value.forEach((it) => {
							if (oldValue.indexOf(it) === -1) {
								newItem = it;
							}
						});
						//取消选中
						if (this.app.config.selectedParallelLine === newItem) {
							this.app.data.selectedParallelLine = '';
						}

						//根据y值排序
						let index = this.app.config.allParallelLinesName.indexOf(newItem);
						index++;
						let segmentShow = $.extend([], this.app.config.segmentShow);
						segmentShow.splice(segmentShow.indexOf('y' + index), 1);
						segmentShow.sort((a, b) => {
							return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
						})

						//设置新线位置
						let preY = null,
							nextY = null;
						if (oldValue.length === 3) {
							preY = this.app.data[segmentShow[0]] + this.app.config[segmentShow[0]];
							nextY = this.app.data[segmentShow[1]] + this.app.config[segmentShow[1]];
						} else {
							preY = this.app.data[segmentShow[2]] + this.app.config[segmentShow[2]];
							nextY = this.app.data[segmentShow[3]] + this.app.config[segmentShow[3]];
						}

						this.app.data['y' + index] = (preY + nextY) / 2 - (this.app.config['y' + index] + this.app.data['y' + index]);
					}
					break;
				}
			case 'animateShow':
				{
					break;
				}
			case 'reset':
				{
					if (!value) {
						this.group.attr('transform', "");
						this.transformPosition = {
							x: 0,
							y: 0
						};
					}
					break;
				}
			case 'selectedParallelLine':
				{
					if (Snap.select('.parallelLineSelected')) {
						Snap.select('.parallelLineSelected').removeClass('parallelLineSelected');
					}
					if (value) {
						let target = Snap.select('.' + value);
						target.addClass('parallelLineSelected');
					}
					break;
				}
		}
	}

	/**
	 * 更新公式
	 * @param item
	 * @param value
	 */
	updateFormula(item, value) {
		switch (item) {
			case 'segmentRatioShow':
				{
					if (value === 1) {
						this.$formulaContainer.show();
					} else {
						this.$formulaContainer.hide();
					}
					break;
				}
			case 'animateShow':
				{
					if (value > 0) {
						this.app.data.segmentRatioShow = 1;
					}
					break;
				}
			case 'showParallelLines':
				{
					if (value.length > 3) {
						this.$manyFormula.show();
						this.$littileFormula.hide();
					} else {
						this.$manyFormula.hide();
						this.$littileFormula.show();
					}
					break;
				}
			case 'formulaNeedUpdate':
				{
					break;
				}
		}
		this._updateFormulaText();
	}

	/**
	 * 更新公式文字
	 * @private
	 */
	_updateFormulaText() {
		if (!this.app.data) {
			return;
		}
		let segmentShow = this.app.config.segmentShow;

		//根据y值排序
		segmentShow.sort((a, b) => {
			return this.app.config[a] + this.app.data[a] > this.app.config[b] + this.app.data[b]
		})
		console.log(segmentShow)

		//提取公式所需数据
		let data = [],
			data1 = [],
			data2 = [],
			preLineData = null;
		for (let i = 1; i < segmentShow.length; i++) {
			let index = parseInt(segmentShow[i][1]) - 1;
			let preIndex = parseInt(segmentShow[i - 1][1]) - 1;
			let y = this.app.config[segmentShow[i]] + this.app.data[segmentShow[i]];
			let preY = this.app.config[segmentShow[i - 1]] + this.app.data[segmentShow[i - 1]];
			let names = this.app.config.pointsNameArr[index];
			let preNames = this.app.config.pointsNameArr[preIndex];
			let length = Math.round(((y - preY) * 100 / this.app.config.pixelToLength)) / 100;
			length = length < 0.01 ? 0 : length;
			data1.push(preNames[0] + names[0]);
			data1.push(length);
			data2.push(preNames[1] + names[1]);
			data2.push(length);

		}
		data = data1.concat(data2);

		let indexOfZeroIndex = data.indexOf(0);
		if (indexOfZeroIndex != -1) { //线段长度有0
			this._updateEqualFormulaText(true, data);
		} else {
			this._updateEqualFormulaText(false)
		}

		//更新公式
		if (this.app.data.showParallelLines.length === 3) {
			this._updateLittleFormulaText(data);
		} else {
			this._updateManyFormulaText(data)
		}
	}

	/**
	 * 更新三条线时公式文字
	 * @param data 公式数据,格式形如:['AB',1,'BC',1,'DE',1,'EF',1];
	 * @private
	 */
	_updateLittleFormulaText(data) {
		/* data的格式如下
		 data = ['AB',1,'BC',1,'DE',1,'EF',1];
		 */
		if (data.length < 8) {
			this.$littileFormula.hide();
			return;
		} else {
			this.$littileFormula.show();
		}
		//写入DOM
		for (let i = 0; i < data.length; i += 2) {
			let index = i % 4;
			if (i < 4) {
				this._setFormulaTextToDom({
					container: this.$littileF_rowTxt1,
					type: 1,
					text: data[i],
					index: index
				});
			} else {
				this._setFormulaTextToDom({
					container: this.$littileF_rowTxt2,
					type: 1,
					text: data[i],
					index: index
				});
			}
		}
		let ratio = parseFloat((data[1] / data[3]));
		ratio = Math.round(ratio * 100) / 100;
		if (ratio < 0.01) {
			this.$littileF_verMid.text('x');
			this.$littileF_verMid.css("margin-top", "-0.2em");
			this.$littileFormula.find('.remark').css('display', 'block');
		} else {
			this.$littileF_verMid.text(ratio);
			this.$littileF_verMid.css("margin-top", "auto");
			this.$littileFormula.find('.remark').css('display', 'none');
		}

	}

	/**
	 * 更新多与三条线时公式文字
	 * @param data 公式数据,格式形如:['AP1',1,'P1B',1,'BC',1,'DQ1',1,'Q1E',1,'EF',1];
	 * @private
	 */
	_updateManyFormulaText(data) {
		/* data的格式如下
		 data = ['AP1',1,'P1B',1,'BC',1,'DQ1',1,'Q1E',1,'EF',1];
		 */

		/*
		 处理长度为0的情况
		 */
		if (data.length < 8) {
			this.$manyFormula.hide();
			return;
		} else {
			this.$manyFormula.show();
		}

		this._normalize(data);
		//删除多余项
		let showLength = data.length / 4 - 1;
		for (let i = 0; i < 4; i++) {
			if (i > showLength) {
				let iIndex = i * 2;
				this.$manyF_rowTxt1.find("i").eq(iIndex).hide();
				this.$manyF_rowTxt1.find("i").eq(iIndex + 1).hide();
				this.$manyF_rowTxt2.find("i").eq(iIndex).hide();
				this.$manyF_rowTxt2.find("i").eq(iIndex + 1).hide();
				this.$manyF_rowTxt3.find("span").eq(i + 1).hide();
				if (i > 0) {
					this.$manyF_rowTxt1.find("em").eq(i - 1).hide();
					this.$manyF_rowTxt2.find("em").eq(i - 1).hide();
					this.$manyF_rowTxt3.find("em").eq(i - 1).hide();
				}
			} else {
				let iIndex = i * 2;
				this.$manyF_rowTxt1.find("i").eq(iIndex).show();
				this.$manyF_rowTxt1.find("i").eq(iIndex + 1).show();
				this.$manyF_rowTxt2.find("i").eq(iIndex).show();
				this.$manyF_rowTxt2.find("i").eq(iIndex + 1).show();
				this.$manyF_rowTxt3.find("span").eq(i + 1).show();
				if (i > 0) {
					this.$manyF_rowTxt1.find("em").eq(i - 1).show();
					this.$manyF_rowTxt2.find("em").eq(i - 1).show();
					this.$manyF_rowTxt3.find("em").eq(i - 1).show();
				}
			}
		}

		//写入DOM
		let index = 1;
		for (let i = 0, j = data.length / 2; i < data.length / 2; i++, j++) {
			if (i % 2 === 0) { //处理线段文字
				this._setFormulaTextToDom({
					container: this.$manyF_rowTxt1,
					type: 1,
					text: data[i],
					index: i
				});
				this._setFormulaTextToDom({
					container: this.$manyF_rowTxt2,
					type: 1,
					text: data[j],
					index: i
				});

			} else { //处理线段长度
				this._setFormulaTextToDom({
					container: this.$manyF_rowTxt3,
					type: 2,
					text: data[i],
					index: index
				});
				index++;
			}
		}

	}

	/**
	 * 更新等于0情况
	 * @param hasZero 是否有0
	 * @param data 数据
	 * @private
	 */
	_updateEqualFormulaText(hasZero, data) {
		this.$equalFormulas.hide();
		if (hasZero) {
			let zeroIndex = 0;
			//删除为0的元素,并显示
			for (let i = 1; i < data.length / 2; i += 2) {
				if (data[i] === 0) {
					let seg1Index = i - 1,
						seg2Index = data.length / 2 + i - 1,
						zeroText1 = data[seg1Index],
						zeroText2 = data[seg2Index];
					let $equalFormula = this.$equalFormulas.eq(zeroIndex);

					zeroIndex++;
					this._setFormulaTextToDom({
						container: $equalFormula.find('.rowTxt:first'),
						type: 1,
						text: zeroText1,
						index: 0

					})
					this._setFormulaTextToDom({
						container: $equalFormula.find('.rowTxt:first'),
						type: 1,
						text: zeroText2,
						index: 2

					})
					$equalFormula.show();
					data.splice(seg1Index + 1, 1);
					data.splice(seg1Index, 1);
					seg2Index = seg2Index - 2;
					data.splice(seg2Index + 1, 1);
					data.splice(seg2Index, 1);
					i -= 2;
				}
			}
		}
	}

	/**
	 * 将公式写入到文档中
	 * @param 文字数据
	 * {   container : null, 数据项的外层,指$manyF_rowTxt1,2,3
	        type : null, 数据项的类型,1,线段名称,2,线段长度
	        text : null, 数据项的文字
	        index: null 数据项的序号
	    }
	 * @private
	 */
	_setFormulaTextToDom(textData) {
		if (textData.type === 1) { //type === 1

			let segName = textData.text;
			let letters = [textData.container.find("i").eq(textData.index), textData.container.find("i").eq(textData.index + 1)];
			let letterIndex = 0;
			for (let i = 0; i < segName.length; i++) {
				let currChar = segName[i];
				if (currChar === 'P' || currChar === 'Q') {
					letters[letterIndex].html(`${segName[i]}<sub class="TimesNewRoman times36">${segName[i+1]}</sub>`);
					i++;
				} else {
					letters[letterIndex].html(segName[i]);
				}
				letterIndex++;
			}

		} else { //type === 2

			let target = textData.container.find("span").eq(textData.index);
			target.text(textData.text);

		}
	}

	/**
	 * 将数据变成以1为基底的形式
	 * @param data 原始数据
	 * @returns {*} 标准化后的数据
	 * @private
	 */
	_normalize(data) {
		let min = parseFloat(data[1]);
		for (let i = 1; i < data.length / 2; i += 2) {
			if (min > parseFloat(data[i])) {
				min = parseFloat(data[i]);
			}
		}
		for (let i = 1; i < data.length; i += 2) {
			data[i] = Math.round((data[i] / min) * 100) / 100;
		}
		return data;
	}

}

redpajama_set_name: RedPajamaGithub


Based in Hell's Kitchen, Raindance NYC is the New York Hub of the world renowned Raindance Film Festival.
Raindance New York supports and promotes independent films and filmmakers by offering film training and networking opportunities in New York.
From new and emerging to industry pros, Raindance connects, trains, supports, and promotes visual storytellers through every step of their career, providing information and advice on all aspects of film, from shorts, features, documentaries, web series and new media.


text:
Las lenguas yaka son un subdivisión de las lenguas bantúes, codificado como subgrupo H.30-40 en la clasificación de Guthrie. De acuerdo con Nurse & Philippson (2003) H.10 forman un grupo filogenéticamente válido. Las lenguas del grupo filogenético son:
 Yaka, Suku–Sonde, Mbangala, Shinji (Yungo), (H40) Hungana, (B80) Yansi (posiblemente varias variedades)

Las lenguas yaka parecen ser el subgrupo bantú más cercano a las lenguas kongo.

Comparación léxica
Los numerales en diferentes lenguas yaka son:
{|class=wikitable style=text-align:center;
|-
! GLOSA
! Hungana !! Mbangala !! Suku !! Yaka(Ngongo)
! PROTO-YAKA
|-
| '1' || móʃ(i) || -moʃi || mosi || mwisi || *mosi
|-
| '2' || yôl || -yadi || zodi || bwol || *bwadi
|-
| '3' || tát || -tatu || tatu || bétat || *tatu
|-
| '4' || yá || -wana || ya || bewan || *wa-na
|-
| '5' || tân || -tanu || taːnu || bétan || *taːnu
|-
| '6' || sámán || samanu || saːmbanu || besaman || *saːmanu
|-
| '7' || nsámbwar || sambwadi || tsambwadi || nsambwadi || *-sambwadi
|-
| '8' || kínan || nake || nana || kenan || *nana
|-
| '9' || kivá || di-vwa || vwa || kebva || *-bwa
|-
| '10' || kwǐm || -kumi || kumi || ékwom || *kumi
|}

Referencias

Bibliografía
Nurse & Philippson (2003), The Bantu Languages.
 Nordhoff, Sebastian; Hammarström, Harald; Forkel, Robert; Haspelmath, Martin, eds. (2013). "Yaka". Glottolog. Leipzig: Max Planck Institute for Evolutionary Anthropology.

redpajama_set_name: RedPajamaWikipedia


Op de eerste BBQ dit jaar!
Earned the Verified Adventure (Level 2) badge! Earned the 99 Bottles (Level 8) badge!
Hints of coffee, but not so darkly roasted. The oats balance the taste.
Earned the Middle of the Road (Level 74) badge! Earned the Brewery Pioneer (Level 23) badge!
Earned the 99 Bottles (Level 100) badge! Earned the Heavy Weight (Level 13) badge! Earned the Oat of this World! badge!
Earned the 99 Bottles (Level 60) badge! Earned the Flamenco (Level 26) badge!
Earned the St. Patrick's Day (2019) badge! Earned the Heavy Weight (Level 93) badge! Earned the Find the Source (Level 8) badge!
Earned the International Women's Day (2019) badge! Earned the Flamenco (Level 11) badge!
Earned the International Women's Day (2019) badge! Earned the Middle of the Road (Level 35) badge!
Earned the Photogenic Brew (Level 30) badge! Earned the Wheel of Styles (Level 9) badge! Earned the Heavy Weight (Level 4) badge!
Lots of CO2. Bit of a candy scent. Reminds me of bubblegum. Description tells us it's plums. Wouldn't have guessed lol. Flavor is weird sweetish sour. Not much left of any malts. Lacks body and a descent aftertaste. Bit watery.


text:
Home News Alireza Jahanbakhsh's Seagulls future up in the air
Alireza Jahanbakhsh's Seagulls future up in the air
The Iran international has struggled to impress since a £17million from AZ Alkmaar in 2018.
Graham Potter will consider the future of Alireza Jahanbakhsh over the summer but insists Brighton's former record signing could still have a part to play at the Amex Stadium.
Iran international Jahanbakhsh has struggled to impress since a GBP 17million from AZ Alkmaar in 2018.
The out-of-favour winger has been restricted to just 20 minutes of action in Albion's eight games since football resumed and appears surplus to requirements.
Seagulls head coach Potter understands the player's concerns about a lack of game time and admits the situation needs to be addressed.
"He'll be frustrated of course because he wants to play and I understand that," said Potter.
"He's been great around the club, great with me, he gives his best all the time but he's like any footballer – they want to play more.
"So it's something we have to think about over the break and do what's right for him, what's right for the club. He's a good player and he can help us.
"But again you can understand it from his perspective that he wants to play more regularly than he has."
Jahanbakhsh appeared to have kick-started his Seagulls career with two goals in as many games – including a spectacular bicycle kick against Chelsea – either side of the turn of the year.
But, going into the final game of a difficult campaign, the 26-year-old has started only three top-flight matches since Potter succeeded Chris Hughton last summer.
Albion complete the season away to in-form Burnley on Sunday after guaranteeing survival with a goalless draw against Newcastle on Monday.
Sean Dyche's Clarets have gone seven matches unbeaten to guarantee a top-half finish.
"We know it'll be a very tough game – you only need to look at Burnley's points since lockdown, what they've achieved over the last few years," said Potter.
"It's an amazing job there that Sean has done and I have the utmost respect for him and for what they've achieved."

redpajama_set_name: RedPajamaCommonCrawl


text:
You are here: Home / Archives for Paddy Driscoll
Heritage Auctions Offering Rare NFL Program From 1920
April 29, 2018 By Bob D'Angelo
A rare slice of NFL history in its infancy will be up for grabs during Heritage Auctions' current catalog auction, which takes place May 17-18 in Dallas. A program from an Oct. 24, 1920, game between the host Rock Island Independents and the Racine Cardinals shows the National Football League during its first season, when a loose confederation of teams combined to form … [Read more...]


Dry run. Accompanied by dense clouds and headwind, narrow, hilly roads lead you to the foot of the mountain. With pure muscle power and steady steps, you hike each kilometre of the mountain. Completely in your element, not even the large water droplets falling from the heavens can stop you from soldiering on.
These lightweight, waterproof and weatherproof cycling trousers will keep you feeling pleasantly dry even in heavy downpours. Stripped back to the bare essentials, the stretch inserts at the bottom and outside leg provide maximum freedom of movement. Velcro closures to adjust the leg width make it easier to get into and out of these trousers. The elastic waistband and silicone strip ensure a perfect hold. The reflective print ensures high visibility on the road. Designed to suit cycling posture, these SCUDO Val Müstair Trousers will protect you from rain, wind and cold. These trousers can be packed up small and stored in your backpack. Ideal for mountain biking and even the daily commute.


According to a report by entertainment columnist Ricky Lo, Marjorie Barretto does not like the idea of her sister, Gretchen Barretto supporting the series 'Forevermore'.
Watching the series, Gretchen also became fond of Liza that she often "like" Liza's photos on Instagram.
But, supposedly Marjorie thinks that Liza is her daughter's rival. Liza and Julia Barretto are batch mates on Star Magic Circle Batch 2013. Rumor is at the beginning, it looked that Julia will be the star of the batch; but slowly, Liza has emerged as the new favorite primarily because of her acting skills.
Meanwhile, being batch mates for Star Magic Circle, Julia and Liza became friends, also with Janella Salvador. Janella clarified that there is no competition going around them and they are really close friends because their personalities jives with each other.


Bright Brown was established in 1977 and today, Bright Brown continue to build on our enviable reputation for providing excellent advice and a first class service to our business and personal clients alike. In addition to traditional accounting, auditing and tax services we also provide advice on how to improve and develop your business.
Bright Brown work in partnership with our clients to deliver an extensive range of value for money professional services tailored to the needs of any individual or business client. We pride ourselves on delivering these services promptly and efficiently. Clients pay only for the services they require and we can offer fixed fee prices agreed in advance.
All of Bright Brown's clients have their own personal account manager who provides a single point of contact to listen to the needs of each client and to deliver a tailored range of accountancy services to meet those needs. This single point of contact enables account managers to respond quickly to any changing client requirements.
Bright Brown have invested heavily in a state of the art IT infrastructure to process and protect client's data, confidentially and securely. Both HM Revenue & Customs and Companies House have endorsed and accredited the software that Bright Brown use. As such, Bright Brown are able to securely exchange documents electronically with clients, as well as file accounts, tax returns and forms electronically with HM Revenue & Customs and Companies House. Bright Brown have further invested in developing an IT capability for video conferencing. This capability enables all clients to have a face to face conversation at a time of their choosing and convenience.


text:
So Cool! The Combermere Abbey Ice House
On the edge of the woods, behind Combermere Abbey's Walled Garden, sits a very curious brick construction. The rather eccentric brickwork is obviously modern, but it frames an entrance, with much older stone steps – which lead down into the earth. The roof of the passage is barrel-vaulted, well built in local brick, and a few yards in a broader, circular structure can be seen – going down deep into the ground. This is the Abbey's ice house, and though we don't know when it was constructed, we certainly know why – and how it served its purpose.
The entrance to the Combermere Abbey ice house
In this country and in this form ice houses date back to 1619. The first Stuart king of England, James I, ordered the building of the first ice house in England – at Greenwich. There had been 'ice pits' previously, but they were crude constructions and were far less sophisticated – and efficient – than brick-built ice houses.
The Greenwich ice house. Still in use when this illustration was made in 1722.
King James had another ice house built at Hampton Court Palace between 1625 and 1626. This one was huge; a circular, brick-lined structure thirty feet deep and sixteen feet in diameter, almost completely subterranean, and covered with a thatched roof. This design, with modifications, set the standard for the next two hundred and fifty years.
King Charles II was the next monarch to commission the building of an ice house in this country. His was built in 1660 in what was then Upper St James's Park and is now Green Park. Charles was fascinated by science, and also enjoyed his food, so it brought together two passions.
Their popularity really took off in the next century, especially when gentlemen and aristocrats returned from The Grand Tour with an enthusiasm for ice creams and other culinary delicacies which needed to be chilled during their manufacture. Ice houses became very popular indeed, both on country estates like Combermere, and in the gardens of urban villas. Over the years very many have been dismantled or filled in – for obvious safety reasons – though some of those remaining were used as (rather chilly) air raid shelters during the Second World War.
Ice houses were, understandably, built in shaded or naturally cool areas. Sometimes they were underneath other buildings, or they were built into north-facing ha-has. Most seem to have been built in woodland, as at Combermere.
They varied in design, but the basic form comprised a narrow corridor, usually built in brick, descending under the ground level. At the end it usually met a low (often stone) lip, against which barrows could be halted, and then there was a square or circular pit, at least ten feet deep, and again brick-lined. The roof was often made up of a brick sphere, or could more simply be capped off with stone. The floor tapered to a grid, which allowed melted water to seep into a sump, and then drain away.
Stone steps lead down into the ice house
The entrance passage is narrow and low, to keep the cool air in, and well-made in Cheshire brick
The passageway leads to the circular chamber which is sunk into the earth. The brickwork is as good as you would see on a house.
Ice wasn't made in ice houses; it was stored there. It was made by nature – in the usual way, during cold weather. On harsh winter days pond ice and snow would be harvested by garden staff, and shovelled into the ice house. The insulation properties of the structure were so good that a surprisingly large amount would still be there by the following summer – and, sometimes, the summer after that. The snow and ice was used for cooling purposes; either for chilling wine, cooling kitchen containers prior to cooking, or in the dishes themselves. Another culinary trick brought back from the Mediterranean countries was the use of snow and ice for preserving foods – long before the electric refrigerator.
As well as harvesting and preserving it locally, ice was brought into the country by ship from colder climates. Needless to say, rather a lot of the ice melted during transportation, though not as much as one might think. Ice was greatly prized in India during the Raj, and the British ruling class were happy to pay for it. Ships brought ice all the way from North America and Canada, and the merchants worked on a rule of thumb that half of the ice loaded would still be frozen by the time it was unloaded in India.
Ice shipped into England tended to come from Norway. Quite how the sailors coped with the melted ice I don't know. Presumably it was bailed out as they went. Ice was certainly imported into London and Bristol by sea, and rapidly transported to ice houses within those cities. However, away from the ports transporting such a bulky and heavy cargo across land, and on very poor roads, must have been a tedious and expensive business. With the coming of the railways – broadly speaking from the 1840s onwards – ice could be distributed around the country far more quickly, and was carried in specially-adapted, insulated boxvans (ice was also used to keep food fresh when it was moved by rail; carcasses were hung from iron rails fitted to the roof, over a bed of ice).
The popularity of ice houses was linked to adventurous fashions in cooking, and in particular fabulous confections. Confectionary chefs were usually French or Italian and were very highly paid. They stood apart from the hierarchy of kitchen staff and only answered to the lady of the house. They operated in their own kitchens, away from the heat of the main kitchens, for practical reasons – but this allowed them to create their own fiefdoms, where sometimes only their native language was spoken, the better to set themselves apart from the other servants. The confectionery kitchens often had windows on a south-facing wall as good light was needed for the sculpting of elaborate dishes.
These specialist cooks made blancmanges, jellies, aspics and bombes, ice creams and sugar-based dishes of all descriptions, sizes and flavours – created to impress with both their extravagance as well as their taste.
Pyramids of confections, from a specialist French cookery book, all of which required ice for their creation
In the mid-Eighteenth century landscape gardeners often incorporated an ice house into their designs. The eighteen foot-deep ice house built by Lancelot 'Capability' Brown at Croom park – the Earl of Coventry's country estate near Pershore – can still be seen today.
An ice house design of 1818
The ice house at Syon Park, by the Thames near Brentford, is another survivor. The one which can be seen nowadays was the second on the same site. Demand for ice from the kitchen was such that the earlier ice house was enlarged in 1820, with two separate chambers and double doors to aid insulation. Servants transported the ice to the confectionery chefs in huge zinc-lined wooden chests.
Ice house designs from Stanmer House near Brighton in East Sussex, and Lancing Manor in West Sussex
Many country houses have legends of secret passages associated with them, and some architectural historians have suggested that the enigmatic entrances to ice houses – their original purpose long forgotten – may have been the source of this mythology.
Sadly, as I say, we don't know when the ice house at the Abbey was built. The lake would probably have provided more than enough ice every winter, but when it was needed it would have been quite a trek to transport it to the kitchens – getting on for half a mile.
A house such as Combermere would certainly have been grand enough to warrant one. Guests to the Abbey could not have failed to have been impressed by the dishes which could be created with the use of ice – especially in high summer. And if you were served the finest confections during your meal at least you had the comfort of knowing that you were considered to be worth impressing!
We can assume that the Combermere ice house was in place during the stay of the Empress of Austria in 1881 and 1882, and although she ate very sparingly so as to preserve her tiny waist, she might have toyed with delightful flavoured ices and served other confections to her guests. If the ice house was sixty years or more older, it seems highly likely that the first Viscount Combermere would have had his cooks serve the very best and most elaborate confections to his very august guest, the Duke of Wellington. So much effort was expended preparing for the Duke's visit, including the building of a whole new wing on the Abbey, complete with a ballroom, that if there wasn't an ice hour before, the one we see today might well have been built specifically for his brief stay.
Nowadays, of course, we just reach into the 'fridge – in houses grand and not so grand alike – without any thought for how it works. It's far more convenient, but somehow nothing like as romantic as the winter's ice, preserved in a specially-built house, and barrowed down to the kitchen by strong lads.
Please note that the ice house is dangerous – even the steps leading into it are very worn and slippery. If you are a visitor to the Abbey do not attempt to go in it. Thank you.


text:
Norman Finkelstein: Charlie Hebdo is Sadism, Not Satire
by Mustafa Caglayan
Turkish Press
https://www.meforum.org/campus-watch/22180/norman-finkelstein-charlie-hebdo-is-sadism-not
In Nazi Germany, there was an anti-Semitic weekly newspaper called Der Stürmer.
Run by Julius Streicher, it was notorious for being one of the most virulent advocates of the persecution of Jews during the 1930s.
What everybody remembers about Der Stürmer was its morbid caricatures of Jews, the people who were facing widespread discrimination and persecution during the era.
Its depictions endorsed all of the common stereotypes about Jews – a hook nose, lustful, greedy.
"Let's say, ... amidst all of this death and destruction, two young Jews barged into the headquarters of the editorial offices of Der Stürmer, and they killed the staff for having humiliated them, degraded them, demeaned them, insulted them," queried Norman Finkelstein, a professor of political science and author of numerous books including "The Holocaust Industry" and "Method and Madness."
"How would I react to that?," said Finkelstein, who is the son of Holocaust survivors.
Finkelstein was drawing an analogy between a hypothetical attack on the German newspaper and the deadly Jan. 7 attack at the Paris headquarters of the satirical magazine Charlie Hebdo, that left 12 people dead, including its editor and prominent cartoonists. The weekly is known for printing controversial material, including derogatory cartoons about the Prophet Muhammad in 2006 and 2012.
The attack sparked a global massive outcry, with millions in France and across the world taking to the streets to support freedom of the press behind the rallying cry of "Je suis Charlie," or "I am Charlie."
What the Charlie Hebdo caricatures of the Prophet Muhammad achieved was "not satire," and what they provoked was not "ideas," Finkelstein said.
Satire is when one directs it either at oneself, causes his or her people to think twice about what they are doing and saying, or directs it at people who have power and privilege, he said.
"But when somebody is down and out, desperate, destitute, when you mock them, when you mock a homeless person, that is not satire," Finkelstein said.
"That is, I give you the word, sadism. There's a very big difference between satire and sadism. Charlie Hebdo is sadism. It's not satire"
The "desperate and despised people" of today are Muslims, he said, considering the number of Muslim countries racked by death and destruction as in the case of Syria, Iraq, Gaza, Pakistan, Afghanistan and Yemen.
"So, two despairing and desperate young men act out their despair and desperation against this political pornography no different than Der Stürmer, who in the midst of all of this death and destruction decide its somehow noble to degrade, demean, humiliate and insult the people. I'm sorry, maybe it is very politically incorrect. I have no sympathy for [the staff of Charlie Hebdo]. Should they have been killed? Of course not. But of course, Streicher shouldn't have been hung. I don't hear that from many people," said Finkelstein.
Streicher was among those who stood trial on charges at Nürnberg, following World War II. He was hung for those cartoons.
Finkelstein said some might argue that they have the right to mock even desperate and destitute people, and they probably have this right, he said, "But you also have the right to say 'I don't want to put it in my magazine ... When you put it in, you are taking responsibility for it."
Finkelstein compared the controversial Charlie Hebdo caricatures to the "fighting words," doctrine, a category of speech penalized under American jurisprudence.
The doctrine refers to certain words that would likely cause the person to whom they are directed, to commit an act of violence. They are a category of speech unprotected by the First Amendment.
"You are not allowed to utter fighting words, because they are equivalent of a smack to the face and it is asking for trouble," Finkelstein said.
"So, are the Charlie Hebdo caricatures the equivalent of fighting words? They call it satire. That is not satire. It is just epithets, there is nothing funny about it. If you find it funny, depicting Jews in big lips and (a) hook nose is also funny."
Finkelstein pointed to the contradictions in the Western world's perception of the freedom of the press by giving the example of the pornographic magazine Hustler, whose publisher, Larry Flynt, was shot and left paralyzed in 1978 by a white supremacist serial killer for printing a cartoon depicting interracial sex.
"I don't remember everyone celebrating 'We are Larry Flynt' or 'We are Hustler,'" he said. "Should he have been attacked? Of course not. But nobody suddenly turned this into a political principle of one side or the other."
The West's embrace of the Charlie Hebdo caricatures was because the drawings were directed at and ridiculed Muslims, he said.
The characterization by the French of Muslims as being barbaric is hypocritical considering the killings of thousands of people during France's colonial occupation of Algeria, and the French public's reaction to the Algerian war from 1954 to 1962, according to Finkelstein.
The first mass demonstration in Paris against the war "did not come until 1960, two years before the war was over," he said. "Everybody supported the French annihilatory war in Algeria."
He said French philosopher Jean Paul Sartre's apartment was bombed twice in 1961 and 1962, as was the office of his magazine, Les Temps Modernes, after he came out in full force against the war.
Finkelstein, who has been described as an "American radical," said the pretensions of the West about Muslim attire exposed a dramatic contradiction in the face of the West's attitude toward natives in lands they occupied during colonialism.
"When Europeans came to North America, the thing they said about the native Americans was that they were so barbaric, because they walked around naked. The European women were wearing three layers of clothes. Then they came to North America, and decided that the native Americans were backward because they all walked around naked. And now, we walk around naked, and we say that the Muslims are backward because they wear so much clothes," he said.
"Can you imagine anything more barbaric? Banning women wearing headscarves?" he asked, referring to the 2004 ban on headscarves in French public service jobs.
Finkelstein's work, accusing Jews of exploiting the memory of Holocaust for political gain and criticizing Israel for oppressing the Palestinians, has made him a controversial figure even within the Jewish community.
He was denied a tenure as a professor at DePaul University in 2007 after a highly publicized feud with fellow academic Alan Dershowitz, an ardent supporter of Israel. Dershowitz reportedly lobbied the administration of DePaul, a Roman Catholic university in Chicago, to deny him tenure.
Finkelstein, who currently teaches at Sakarya University in Turkey, said the decision was based on "transparently political grounds."
Related Topics: DePaul University receive the latest by email: subscribe to the free mef mailing list


The Artists' Legal Outreach can help.
The Artists' Legal Outreach (ALO) is a non-profit society consisting of a group of volunteer lawyers and law students committed to working with artists and arts organizations. The ALO offers resources, workshops, and clinics where artists can meet confidentially with an experienced lawyer. Every artistic discipline is welcome, all for the price of a donation.
The ALO began as a pilot project of the Alliance for Arts + Culture, called the Arts and Performers Legal Advice and Workshop Series (APLAWS). APLAWS was the creation of the late Burt Harris, a friend and colleague to many in the arts, who for many years tried to get a legal advice clinic for artists off the ground.
Visit artistslegaloutreach.ca for a calendar of ALO's upcoming clinics, toolkits, a database of legal information for artists and cultural workers, and to complete an intake form for receiving legal assistance.


In the current conditions of global competition, the development of new mining technologies, the requirements to labor resources, their skills and creative potential are increasing. The tasks facing the mining industry cannot be solved without highly qualified personnel, especially managers, engineers and technicians, specialists who possess the knowledge and competences necessary for the development of science and technology of mining, and ensuring mining industrial safety. The authors analyze personnel problems and financing of mining higher education, conclude that there is a need to develop social partnership and diversify the sources of funding for training, advanced training and retraining of personnel for mining and processing of solid mineral deposits.


1) The Village revenue officer has no discretion to give any ruling. The issue should be referred to the Irrigation department.
Kartick Chandra Mondal v. Chairman Wbseb & Ors.
3) File an application before the Teshilsdar and the Irrigation department.
4) Please do click upon the like thumbs up tab shown below this reply format in token of appreciation for my having replied to your query.
1) In order to dig borewell, not sure whether you have obtained permission from Mandal Revenue Officer new ANDHRA PRADESH WATER, LAND AND TREE ACT (WALTA).
2) It is a simple procedure under single window system where in upon payment of Rs.100/- towards application fee to Mandal Revenue Officer,you can apply for permission for new well in Form – 2 along with a demand draft for Rs.1000/- in the name of concerned District Deputy Director, Ground Water Department, towards groundwater survey charges.
3) After receiving the application from the farmer, the Mandal Revenue Officers are requested to verify spacing norms of 250 meters from the existing bore well of drinking water in the field to the proposed site for new well.
5) The escalation matrix is MRO->RDO->DRO-> Collector.
sir take the permission of the municipality the patwari then do the needful .


text:
[2008 ROSTER] 2008 40-Man Roster And Payroll Predictions
40-man Roster 6 comments
The 2008 40-man roster prediction is based only players currently within the organization and will be updated when trades are consummated and free agents are signed.
On November 20th, all teams have to set their 40-man roster. At that time any player that has 4 years of experience (5 years if signed at 18 or under) must be protected on the 40-man roster or be made available for the upcoming rule 5 draft. Of the players not to be protected on the 40-man roster, they may still be added to the Durham Bulls roster in order to be protected from the AAA version of the rule 5 draft.
First, second and third year players will have their salaries determined by the team, but will fall close to the major league minimum which is 390,000 for first year players. Minor leaguers on the 40-man for the first time make $31,250 and second-year players make twice that amount. In addition, six players are arbitration eligible. The 2008 salaries for these players are estimates. We are not including signing bonuses or incentives. For example, Evan Longoria signed a standard minor league contract, but was given a $3 million signing bonus.
A FEW NOTES ON THE 40-MAN ROSTER…
The Rays 40-man roster currently has 37 players. Three players that are currently on the 60-day DL (Rocco Baldelli, Shawn Riggans, Ben Zobrist) will need to be added to the roster by November 20, giving the Rays 40 players.
The Devil Rays have eight players that would be eligible for the rule 5 draft. At this point, we are predicting that three of these players will be added to the 40-man roster. This includes third baseman Evan Longoria, catcher John Jaso and relief pitcher Dale Thayer.
To make room for these players, the Rays will need to remove three players from the roster. The team has a 2008 option on Greg Norton that they are not expected to exercise. In addition, at this point we are predicting the Rays to designate for assignment Scott Dohmann and Grant Balfour. Balfour seems like an easy choice as he is arbitration eligible. Dohmann still has one year left until he is available for arbitration and the Rays may choose to keep him. The only other arbitration eligible player that could be subjected to release would be Gary Glover, but his major league experience gives him the edge.
This leaves 6 players that will be made available in the Rule 5 draft
Jason Pridie: Could be a tough decision after a trong showing at AAA in 2007. A former rule 5 selection by the Twins.
Fernando Perez: No experience above AA. Can't see anybody taking a chance on the speedster in the draft. Will be added to Durham roster to protect from AAA version of draft.
Greg Dupas: Will not be protected
Nick DeBarr: Rule 5 pick by Red Sox in 2007. Has yet to show dominance in minor leagues. Not likely to be protected
Chuck Tiffany: Injured in 2007. Will not be protected.
Chris Nowak: No experience above AA. Similar to Wes Bankston in that he is a big first baseman that has yet to develop power that has been predicted. Likely added to Durham roster to protect from AAA version of draft.
Based on the current roster, the 2008 Tampa Bay Rays will include only 1 player (Al Reyes) with at least 6 years of major league experience.
On opening day, the Rays 40-man roster will feature only three players that will be 30 years old or older (Reyes, Glover, Wheeler).
Robert Rittner says:
I doubt that either Balfour or Dohmann will be removed from the roster. My guess is that Stokes will definitely go and that Ryu or even Orvella might also be released before those two. Perhaps Elliott Johnson or Switzer are also on the bubble.
raysrule07 says:
Perez needs to be protected because someone will take a chance on him. He draws walks, plays very good defense, showed some flashes of power, and he's got speed. Someone in the NL would take a chance on him as a switch-hitter/pinch-runner.
Also, Longoria doesn't need to be protected, but he will probably be added anyway since he's probably going to be the opening day starter.
I don't think there is any question that Perez will be protected. After Desmond Jennings, he is probably the highest rated outfielder in the system. He had a .904 OPS at Montgomery, a terrible hitter's park in a terrible hitter's league, this year.
The Professor says:
RaysRule07...I am assuming Longoria is the third baseman on opening day
Balfour and Dohmann are strictly guesses. You could be right about Orvella and Stokes. Our feeling was...
1. Balfour will be 30 and is arbitration elig. Would the team rather have him at $800K or Orvella at the MLB minimum?
2. The team took a flyer on Dohmann and I just never got the impression that Papa Joe or the team was impressed. He was only ever used in a mop up rolls and spent half the year in the minors.
3. I also think that Orvella and Ryu would have the least chance of making it through waivers. I think some still look at Ryu as a potential starter and somebody would take a flyer on Orvella based on his minor league numbers.
Perez is a tough call. Few hitters are taken in the Rule 5 and even fewer stick with their teams. It is easier to hide a young relief pitcher in the pen. But yes, there is a chance that Perez could be taken.
So let's say Perez is the 4th player added to the roster (not including Longoria). Who else are you dropping from the roster. There are only so many relief pitchers we can drop.
Remember the Rays are still looking to sign a veteran catcher. Do they drop Riggans? Not Likely. So that is another opening they need to make.
I think the trade for Balfour was a good one, and I think the Rays consider him a real find. As with most relievers, that remains a question, but I don't think the relatively small difference in salaries would dissuade them from keeping him.
Dohmann is another story. I never understood why the Rays pursued him so doggedly, but he did do a reasonably good job once in TB, and I am guessing the Rays see him (and Balfour) as having stabilized the bullpen somewhat. He spent the first half in the minors, I think, to try to overcome his wildness, and at Durham he did that brilliantly (2.4BB/9) although the problem returned in TB (4.96/9) but he does not give up a lot of hits and does strike people out.
I do not know all the rules about this, but I cannot imagine them taking even the slightest chance that Perez would get drafted.
The easiest pieces to pick up are relievers, so I doubt the Rays are too worried about losing either Orvella or Ryu. There are teams that probably would select Ryu, but given the strength of our starter pool and his mediocre performance for us (we picked him up last off-season in a minor deal) I don't think they would consider it a big loss.
I feel badly about Orvella who I expected might become an excellent reliever, but his failures are becoming frustrating enough that he just may need a new team. And even should both go, aside from the major league definites, and potential off-season signings, there are still Birkins, Medlock (who I think they like), Ridgway, Switzer and Thayer among others around.
Brock Trader says:
The Blackhawks are taking home the cup this yr, virtually no hesitation about it. Before throughout the 2010 playoffs i thought Chicago was initially ruined because regarding the Hossa curse. three totally different teams, three different years, all making it to the cup finals and yet not winning. Let us discover if he may acutally win one this yr. Along with apart from the actuality, i can not stand Philly meant for reasons that is going to go un-named. Phillys moment within the spot light is certainly finished, down 2-0 they don't have a real chance. Go Hawks!


text:
Smallpox | causes, symptoms and management
Leave a Comment / Diseases and conditions / January 20, 2021 February 3, 2021 / Diseases, smallpox, Variola major, Variola minor
Smallpox as a Biological Weapon
Smallpox is caused by variola viruses, which are large, enveloped, single-stranded DNA viruses of the Poxvirus family and the Orthopoxvirus genus. Variola major strains cause three forms of disease (ordinary, flat type, and hemorrhagic), whereas variola minor strains cause a less severe form of smallpox. Vaccination with vaccinia virus, another member of the Orthopoxvirus genus, protects humans against smallpox because of the high antibody cross-neutralization between orthopoxviruses
Image from Wikipedia
Smallpox is considered one of the most serious bioterrorist threats. It was used as a biological weapon during the French and Indian Wars, (1754 to 1767) when British soldiers distributed smallpox-infected blankets to American Indians. In the 1980s, the Soviet Union developed variola as an aerosol biological weapon and produced tons of virus-laden material annually intended for intercontinental ballistic missiles.
Several factors contribute to the concern about the use of smallpox as a biological weapon:
• Variola can spread from person to person.
• There is no widely available or licensed treatment for the disease.
• It has a high fatality rate.
• Most of the world's population has never been vaccinated or was vaccinated so long ago that immunity to smallpox has waned.
• Variola is relatively stable as an aerosol.
• The infectious dose is small.
Because there are no symptoms at the time of exposure, a covert release of variola may not be detected until sick people begin showing up at doctor's offices and hospitals
Variola virus infection is initiated when the virus comes into contact with the oropharyngeal or respiratory mucosa of a susceptible person. The virus then multiplies in regional lymph nodes. An asymptomatic viremia develops 3 or 4 days after infection, which is followed by further virus replication, probably in the bone marrow, spleen, and lymphatics.
A second viremia begins about 8–10 days after infection and is followed by the first symptoms of illness (prodromal stage), fever and toxemia. The virus localizes in small blood vessels of the dermis and in the oral and pharyngeal mucosa. In the skin, this results in the characteristic maculopapular rash, which evolves into vesicles, then pustules.
Although there are other causes of generalized rash illness which present as vesicles and pustules, the severe prodrome along with the nature of the rash and its evolution distinguishes smallpox from other diseases. The diseases, which can look similar to smallpox, include: varicella, disseminated herpes simplex, disseminated herpes zoster, impetigo, drug eruptions, contact dermatitis, erythema multiforme, enterovirus, scabies, molluscum contagiosum, and monkeypox.
The clinical case definition for smallpox is: an illness with an acute onset of fever of 101°F or higher followed by a rash characterized by firm, deep seated vesicles or pustules in the same stage of development on any body part, without other apparent cause. Laboratory diagnosis is aided by a negative result on one of the rapid diagnostic tests for varicella (i.e., DFA, electron microscopy, and PCR).
Laboratory diagnosis of smallpox can be made by PCR, culture of vesicular or pustular fluid, or culture of the scab; it should only be performed by the LAC Public Health Laboratory, California Viral and Rickettsial Diseases Laboratory, and Centers for Disease Control and Prevention (CDC). (After appropriate consultation to ensure safe packaging and handling, specimens can be sent to the local public health laboratory for forwarding to the state laboratory and then to CDC.)
Electron microscopy of vesicular or pustular fluid, or of the scab, as well as acute and convalescent serologic testing through CDC, can also be performed for diagnosis.
Usually 10-14 days (range 7-19 days).
Officially, only in designated laboratory repositories in USA and Russia. Humans are the only natural host. Naturally occurring smallpox no longer exists, although the threat of smallpox release remains due to concerns that variola virus might exist outside the two official repositories.
Macules, papules, vesicles, pustules, and scabs of the skin and lesions in mouth and pharynx.
The smallpox virus must be continuously transmitted from human to human to survive; humans do not become long–term carriers and animal reservoirs do not exist. Virus is spread by direct contact or inhalation of aerosols; infectious virus is present in oronasal secretions and in scabs from the skin. (The virus in scabs may be tightly bound and spread by this method may be less efficient.) Close contact is usually required for efficient virus transmission; therefore, smallpox mainly spreads to household members and others in close contact. Variola viruses can also be transmitted by individuals who maintain the virus in the throat without clinical signs.
The potential for long–distance aerosol spread is controversial but has been demonstrated under certain conditions such as in hospitals. Transmission on fomites such as contaminated clothing or bedclothes is possible for short periods of time; however, variola does not remain viable for more than 2 days outside a human host. It is sensitive to heat and humidity; most natural epidemics occurred in the winter and spring.
Most significantly, the rash of smallpox is preceded by a prodrome consisting of 1 to 4 days of high fever, malaise, head and body aches, prostration; sometimes nausea, vomiting, abdominal pain, and backache. In 90% of cases, smallpox (variola major) presents as an acute infectious disease characterized by a maculopapular rash (usually starts as small red spots on the tongue and in the mouth), which becomes vesicular on day 3 or 4, then slowly evolves into pustular lesions, deeply embedded into the dermis, by day 6.
Fourteen days after the initial appearance of the rash, most of the lesions have developed scabs. The rash in smallpox usually appears as a single crop with all lesions progressing from the macular to the pustular stage at about the same time.
The mortality rate for smallpox may be as high as 30% in unvaccinated persons and 3% in those with a history of vaccination sometime in the past. (Patients with variola minor have similar signs and symptoms but the disease is less severe and the mortality rate is only about 1%.)
In a minority of instances, smallpox can present as "flat type" smallpox where lesions remain flush with the skin, never becoming elevated even during the pustular stage. This type of presentation is seen in 5% to 10% of cases and results in very severe disease.
Another severe form of smallpox is "hemorrhagic smallpox" which involves extensive bleeding into the skin and almost always results in death. This form of disease, which can be seen in less than 3% of cases, can easily be mistaken for meningococcal sepsis.
Milder disease with a less severe prodrome and a more rapid evolution of lesions can be seen in previously vaccinated individuals.
The management of confirmed or suspected cases of smallpox consists of supportive care, with careful attention to electrolyte and volume status, and ventilatory and hemodynamic support. General supportive measures include ensuring adequate fluid intake (difficult because of the enanthem), alleviation of pain and fever, and keeping skin lesions clean to prevent bacterial superinfection. Currently there are no FDA approved antiviral agents with proven activity against smallpox in humans.
Antiviral agents that have shown some activity in vitro against poxviruses may be available from the CDC under an investigational protocol. ST-246 is a novel agent that is currently undergoing safety and efficacy testing. Additionally, cidofovir, a nucleoside analogue DNA polymerase inhibitor, might be useful if administered within 1-2 days after exposure; however, there is no evidence that it would be more effective than vaccination, and it has to be administered intravenously and causes renal toxicity.
Postexposure prophylaxis
Postexposure prophylaxis for smallpox is the administration of vaccinia vaccine after suspected exposure to smallpox has occurred but before symptoms are present. Immunity generally develops within 8 to 11 days after vaccination with vaccinia virus. Because the incubation period for smallpox averages about 12 days, vaccination within 4 days may confer some immunity to exposed persons and reduce the likelihood of a fatal outcome.
Postexposure vaccination may be particularly important for those vaccinated in the past, provided that revaccination is able to boost the anamnestic immune response. In addition to vaccination, exposed persons should be monitored for symptoms. Temperature should be checked once a day, preferably in evening, for 17 days after exposure for fever (over 38°C).
If a case or cases of smallpox occur, public health authorities will conduct surveillance and implement containment strategies. Ring vaccination will be important and includes identification of contacts of cases and provision of prophylaxis and guidance on monitoring for symptoms. Large-scale voluntary vaccination may be offered to low-risk populations to supplement and address public concerns.
Smallpox Severe Acute Respiratory Syndrome (SARS) Venous thromboembolism | Treatment Cancer and Etiology of carcinogenesis How to stop the spread of Coronavirus disease (COVID-19) Phenylketonuria (PKU): A mutation condition


Eighty students from around America came to Camp Nawaka in East Otis, Massachusetts, to immerse themselves in Sanskrit for five days in May, 2003. This was "Paavinii," the second national Sanskrit camp by Samskrita Bharati, a nonprofit organization dedicated to the revival of Sanskrit language and culture (see July, 2003, issue).
Each day began at 5:45 am with meditation and yoga. Classes on Sanskrit speaking, listening, literature and grammar were taught by volunteer instructors in the style of an ancient Hindu gurukulam.
Participants enjoyed the nearby lake, joined in games, sang devotional songs, relished vegetarian meals and discussed Sanskrit culture and history with Sri Krishna Shastry, founder of Samskrita Bharati.