Prove that $``ff^{-1}(x)$ $=$ $x$ $=$ $f^{-1}f(x)"$ $\implies$ $``$the graph of $f$ and $f^{-1}$ are reflections of each other in the line $y = x"$.

Question: According to the Cambridge International AS & A Level Pure Mathematics $1$ book $(2019$ edition, page $48)$,

The graph of $f$ and $f^{-1}$ are reflections of each other in the line $y = x$. This is because $ff^{-1}(x)=x=f^{-1}f(x)$.When a function $f$ is self-inverse, the graph of $f$ will be symmetrical about the line $y=x$.

But how does $``ff^{-1}(x)$ $=$ $x$ $=$ $f^{-1}f(x)"$ imply $``$the graph of $f$ and $f^{-1}$ are reflections of each other in the line $y = x"$? Can someone prove it?
Answer: The reflection of the point $(\hat x, \hat y)$ in the line $y=x$ is $(\hat y, \hat x)$
So you simply show that for each $\hat x \in \mathcal D(f), \hat y \in \mathcal R(f)$, we have: $$f(\hat x)=\hat y\iff f^{-1}(\hat y)=\hat x$$
Can you show this?
Comment: Yes, I can: $f(\hat x)=\hat y$ $\implies$ $f^{-1}(\hat y)=\hat x$ by the definition of the inverse function of a function. And by the same reason, $f^{-1}(\hat y)=\hat x$ $\implies$ $f(\hat x)=\hat y$. Hence, $f(\hat x)=\hat y\iff f^{-1}(\hat y)=\hat x$.

But how does it prove our original statement?


Inequality of Finite Harmonic Series

Question: I'm asked to prove that for $n\in \mathbb{N}$
$$\frac{1}{1} + \frac{1}{2} +\cdots+\frac{1}{n} \geq 1 + \frac{n}{2}$$
by induction.
I've got a feeling that the problem isn't right (since it isn't true for any $n\in \mathbb{N}$), does anyone know the result and what it should be?
Edit: The author says that the result can be used to prove that the harmonic series diverges.
Comment: It should be $\leq$.
Comment: Here are some collections of proofs of divergence of harmonic series (the one you refer to is the first one).
Steven J. Kifowit and Terra A. Stamps: The Harmonic Series Diverges Again and Again e.g. [here](http://prairiestate.edu/skifowit/harmapa.pdf);
Steven J. Kifowit: More Proofs of Divergence of the Harmonic Series, see e.g. [here](http://prairiestate.edu/skifowit/harm2.pdf).
I think I have seen some question with several proof of this fact at this site, but I cannot find it now.
Comment: @miracle173 thanks for the input, have you read the entire question though?
Answer: Given that the result is supposed to be usable in proving the divergence of the harmonic series, it was probably supposed to be
$$\sum_{k=1}^{2^n}\frac1k=1+\frac12+\ldots+\frac1{2^n}\ge 1+\frac{n}2\;.$$
This can indeed be proved fairly easily by induction on $n$ and can be used to prove the divergence of the harmonic series.
(My earlier answer $-$ that the inequality is the wrong way round $-$ is correct in the sense that the reversed inequality is true, but it's clearly not what the author had in mind.)
Comment: Thank you for your reply. I forgot to mention my edit - does that change anything (I'm no hero at series).
Comment: @Henrik: Yes, it does. Hang on a minute, and I'll change my answer to match.
Comment: @Henrik: Billy and Brian are right. Consider $n = 3$. On the left hand side, you have $1 + \frac{1}{2} + \frac{1}{3} = \frac{11}{6}$, and on the right hand side you have $1 + \frac{3}{2} = \frac{5}{2}$. As $\frac{11}{6} < \frac{5}{2}$, the inequality in the question is the wrong way around.
Comment: Ah. No, given your edit, I don't think my comment *is* what the author intended - it's true, but unhelpful.
Comment: @BrianM.Scott: I think it's worth being clear: the left hand side of your inequality is $1 + \frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{2^n - 1} + \frac{1}{2^n}$, not (as I first read it) $1 + \frac{1}{2} + \frac{1}{4} + \dots + \frac{1}{2^n}$.
Comment: @Billy: It wouldn't have occurred to me to read it that way without more evidence, but I've added a summation to make it absolutely clear.
Comment: @BrianM.Scott A "me too" to Billy's comment.  My eyes went to the expanded version of the sum before they went to the sigma, and I too initially thought it meant $1+\frac 12 +\frac 14+\frac 18 +\cdots+\frac 1{2^n}$
Comment: @David: I take the more obvious progression to be the default. Had I intended powers of $2$, I'd have included at least one early term with an exponent.
Answer: It has been suggested that the inequality be reversed. Certainly we get a correct inequality, unfortunately a fairly uninteresting one. We propose that instead we let
$$f(n)=1+\frac{1}{2}+\frac{1}{3}+\cdots+\frac{1}{2^n},$$
and show that $f(n)\ge 1+\dfrac{n}{2}$
for every integer $n \ge 0$.
It is clear that the result holds when $n=0$. Suppose that the inequality holds at $n=k$. We show that it holds at $n=k+1$.  We have
$$f(k+1)=f(k)+\frac{1}{2^k+1}+\frac{1}{2^k+2}+\cdots +\frac{1}{2^{k+1}}.\tag{$1$}$$
Each of $\frac{1}{2^k+1}$, $\frac{1}{2^k+2}$, and so on up to $\frac{1}{2^{k+1}}$
is $\ge \frac{1}{2^{k+1}}$, and there are $2^k$ such terms. So their sum is $\ge \frac{1}{2}$.
Thus
$$f(k+1)\ge f(k)+\frac{1}{2}\ge 1+\frac{k}{2}+\frac{1}{2}=1+\frac{k+1}{2},$$
and now we have done the induction step.
Remark: This is a somewhat formalized version of the usual argument that the harmonic series diverges.
Answer: Hint: In the following sum, there are $2^{k-1}$ terms, each at least as big as $2^{-k}$; therefore,
$$
\sum_{j=2^{k-1}+1}^{2^k}\frac1j\ge2^{k-1}2^{-k}=\frac12
$$
Furthermore, we also have that
$$
\begin{align}
\sum_{j=1}^{2^n}\frac1j
&=1+\sum_{k=1}^n\sum_{j=2^{k-1}+1}^{2^k}\frac1j
\end{align}
$$

Inequality of Finite Harmonic Series


React Typescript Tag drag to text area

Question: I'm using my react typescript project for  Ant design, I'm find some tutorial for this but any one not see,
this is my conflict, I wanna tag dragging to text area,  so when I type the text and then drag tag next type text and dragging tag,

anyone know solution?
stazkblitz here
Thanks
code here
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Comment, Avatar, Form, Button, List, Input,Tag } from 'antd';
import moment from 'moment';

const { TextArea } = Input;

const CommentList = ({ comments }) => (
  <List
    dataSource={comments}
    header={`${comments.length} ${comments.length > 1 ? 'replies' : 'reply'}`}
    itemLayout="horizontal"
    renderItem={props => <Comment {...props} />}
  />
);

const Editor = ({ onChange, onSubmit, submitting, value }) => (
  <>
    <Form.Item>
      <TextArea rows={4} onChange={onChange} value={value} />
    </Form.Item>
    <Form.Item>
      <Button htmlType="submit" loading={submitting} onClick={onSubmit} type="primary">
        Add Comment
      </Button>
    </Form.Item>
  </>
);

class App extends React.Component {
  state = {
    comments: [],
    submitting: false,
    value: '',
  };

  handleSubmit = () => {
    if (!this.state.value) {
      return;
    }

    this.setState({
      submitting: true,
    });

    setTimeout(() => {
      this.setState({
        submitting: false,
        value: '',
        comments: [
          ...this.state.comments,
          {
            author: 'Han Solo',
            avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
            content:
{this.state.value}
,
            datetime: moment().fromNow(),
          },
        ],
      });
    }, 1000);
  };

  handleChange = e => {
    this.setState({
      value: e.target.value,
    });
  };

  render() {
    const { comments, submitting, value } = this.state;

    return (
      <>

      <Tag color="magenta">magenta</Tag>
      <Tag color="red">red</Tag>
      <Tag color="volcano">volcano</Tag>
      <Tag color="orange">orange</Tag>
      <Tag color="gold">gold</Tag>
      <Tag color="lime">lime</Tag>
      <Tag color="green">green</Tag>
      <Tag color="cyan">cyan</Tag>
      <Tag color="blue">blue</Tag>
      <Tag color="geekblue">geekblue</Tag>
      <Tag color="purple">purple</Tag>

        {comments.length > 0 && <CommentList comments={comments} />}
        <Comment
          avatar={
            <Avatar
              src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
              alt="Han Solo"
            />
          }
          content={
            <Editor
              onChange={this.handleChange}
              onSubmit={this.handleSubmit}
              submitting={submitting}
              value={value}
            />
          }
        />
      </>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));

Comment: Do you want to drag and drop the "Tag" to "Textarea"? If yes, you need to implement [drag and drop](https://www.w3schools.com/html/html5_draganddrop.asp).
Comment: @AjeetShah  yes, but wanna like this image https://i.stack.imgur.com/1Z6an.png, when i type my name is  drop to text area
Answer: There must be a simpler way doing it, the below can be one of the methods solving it.
Hope helps
> import React from 'react'; import ReactDOM from 'react-dom';
> import'antd/dist/antd.css'; import './index.css';
> import { Comment, Avatar,Form, Button, List, Input, Tag, Typography
> }from 'antd'; import
> moment from 'moment'; const { Title, Paragraph, Text, Link } =
> Typography; const { TextArea } = Input;
>
> const CommentList = ({ comments }) => (   <List
>     dataSource={comments}
>     header={`${comments.length} ${comments.length > 1 ? 'replies' :
> 'reply'}`}
>     itemLayout="horizontal"
>     renderItem={props => <Comment {...props} />}   /> );
>
> const Editor = ({ onChange, onSubmit, submitting, value }) => (   <>
>     <Form.Item>
>       <TextArea rows={4} onChange={onChange} value={value} />
>     </Form.Item>
>     <Form.Item>
>       <Button htmlType="submit" loading={submitting} onClick={onSubmit}
> type="primary">
>         Add Comment
>       </Button>
>     </Form.Item>   </> );
>
> class App extends React.Component {   state = {
>     comments: [],
>     submitting: false,
>     value: '',   };
>
>   handleSubmit = () => {
>     if (!this.state.value) {
>       return;
>     }
>     const inputValue = this.state.value
>
>     const inputValueArr = inputValue.split('')
>     let result = []
>     let stack = [], temp = [], flag = true, tagValue = []
>     for(let index in inputValueArr) {
>       if(inputValueArr[index] === '<') {
>         stack.push(inputValueArr[index])
>         flag = false
>       }else if(!flag) {
>         if(inputValueArr[index] !== '>') {
>           tagValue.push(inputValueArr[index])
>         }
>
>         if(stack.length === 1 && inputValueArr[index] === '>') {
>           const beforeValue = temp.join('')
>           result.push({text: beforeValue, isTag: false})
>           const tagText = tagValue.join('')
>           result.push({text: tagText, isTag: true})
>           flag = true
>           stack.pop()
>         }
>       }else if(flag){
>         temp.push(inputValueArr[index])
>       }
>     }
>
>     if(result.length === 0) {
>       const textValue = temp.join('')
>       result.push({text: textValue, isTag: false})
>     }
>     this.setState({
>       submitting: true,
>     });
>
>     setTimeout(() => {
>       this.setState({
>         submitting: false,
>         value: '',
>         comments: [
>           ...this.state.comments,
>           {
>             author: 'Han Solo',
>             avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
>             content: result.map((item, index) => {
>               if(item.isTag) {
>                 return this.generateComment(item.text, item.isTag)
>               }else {
>                 return this.generateComment(item.text, item.isTag)
>               }
>
>             }) ,
>             datetime: moment().fromNow(),
>           },
>         ],
>       });
>     }, 1);   };   generateComment = (text, isTag) => {
>     if(isTag) {
>       return <Tag>{text}</Tag>
>     }else {
>       return text
>     }   }   generateComments = (result) => {
>     console.log(result)
>     return (
>       <Paragraph>
>         {result.map((item, index) => {
>           if(item.isTag) {
>             return (
>
>                 <Text code key={item.text+index}>{item.text}</Text>
>
>               )
>           }else {
>             return
{item.text}

>           }
>
>         })}
>       </Paragraph>
>     )   }   handleChange = e => {
>     this.setState({
>       value: e.target.value,
>     });   };
>
>   render() {
>     const { comments, submitting, value } = this.state;
>
>     return (
>       <>
>         {comments.length > 0 && <CommentList comments={comments} />}
>         <Comment
>           avatar={
>             <Avatar
>               src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
>               alt="Han Solo"
>             />
>           }
>           content={
>             <Editor
>               onChange={this.handleChange}
>               onSubmit={this.handleSubmit}
>               submitting={submitting}
>               value={value}
>             />
>           }
>         />
>       </>
>     );   } }
>
> ReactDOM.render(<App />, document.getElementById('container'));

React Typescript Tag drag to text area


How to send parameters with base64 image string using POST method in iOS?

Question: I have parameters FirstName,LastName,Email & image ,Which need to send in the form of base64.I need appropriate code for it.
Answer: Base64 is used to convert binary data into text.
In your situation only Image needs to be encoded in that format, the rest should be text.
Convert UIImage to Base64 string in Objective-C and Swift
Comment: I have base 64 string but I need how to post parameters along with image strings
Comment: @RakeshBiswal its just a string you post it like any other post param
Comment: @RakeshBiswal you using objective c or swift
Comment: look at my answer here http://stackoverflow.com/questions/25335168/synchronous-https-post-request-ios/25335314#25335314
Comment: Follow my answer in the link above


Find Derivative If of $x^2 \sin(\frac{1}{x^2})$ If Exists

Question: If there is a derivative find it and evaluate it:
$$
f(X)=
\begin{cases}
x^2 \sin(\frac{1}{x^2}), x\neq 0\\
0, x=0\\
\end{cases}
$$
My Answer:
Let assume that the limit exists (one can take the derivative of $x^2 \sin(\frac{1}{x^2})=2x\sin(\frac{1}{x^2})-\frac{2}{x}\cos(\frac{1}{x^2})$
Using the definition of a limit:
$$\lim_{h\to 0}\frac{(x+h)^2\sin\big(\frac{1}{(x+h)^2}\big)-x^2\sin\big(\frac{1}{x^2}\big)}{h} = \lim_{h\to 0}\frac{(x^2+2xh+h^2)\sin\big(\frac{1}{(x+h)^2}\big)-x^2\sin\big(\frac{1}{x^2}\big)}{h}$$
Because we assume the limit exists we can break it up
$$\lim_{h\to 0}\frac{x^2\sin\big(\frac{1}{(x+h)^2}\big)-x^2\sin\big(\frac{1}{x^2}\big)}{h}+\lim_{h\to 0}\frac{2xh\sin\big(\frac{1}{(x+h)^2}\big)}{h}+\lim_{h\to 0}\frac{h^2\sin\big(\frac{1}{(x+h)^2}\big)}{h}$$
$$x^2\lim_{h\to 0}\frac{\big(\sin\big(\frac{1}{(x+h)^2}\big)-\sin\big(\frac{1}{x^2}\big)\big)}{h}+2x\lim_{h\to 0}{\sin\big(\frac{1}{(x+h)^2}\big)}+\lim_{h\to 0}{h\sin\big(\frac{1}{(x+h)^2}\big)}$$
The first limit is by definition, the second limit at a constant is a constant and the third is a bounded function times a function that goes to $0$
$$x^2\cos\big(\frac{1}{x^2}\big)\cdot-2x^{-3}+2x{\sin\big(\frac{1}{x^2}\big)}+0=2x{\sin\big(\frac{1}{x^2}\big)}-\frac{2}{x}\cos\big(\frac{1}{x^2}\big)$$
Is it correct?
Can $x^2 \lim_{h\to 0}\frac{\big(\sin\big(\frac{1}{(x+h)^2}\big)-\sin\big(\frac{1}{x^2}\big)\big)}{h}$ be evaluate using trig identites
Comment: For $x \neq 0$ the function is differentiable because products, compositions and reciprocals (with denominator $\neq 0$) of differentiable functions are differentiable. You can  use chain rule and product rule to write down the derivative.  At $x=0$ differentiabilty is easy.
Answer: The given function is continuous as $\lim_{x \rightarrow 0} h^2 \sin (1/h^2)=0$ by sandwich theorem:$ -h^2 \le  h^2 \sin(1/h^2) \le h^2.$
$RD=f'(0)=\lim_{h \rightarrow 0}\frac{h^2 \sin\frac{1}{h^2}-0}{h}=\lim_{h \rightarrow 0}  h \sin(1/h^2)=0.$
This limit vanishes by sandwich theorem as $-h \le h \sin(1/h^2) \le h,$ Similarly $LD=f'(0)=0.$ so the derivative exists at $x=0$ and it vanishes there.


Track the velocity of a moving view

Question: I'm running into issues when using the VelocityTracker class. Velocity tracking seems to work very well if you are measuring the velocity of touch events on a non-moving view, but as soon as the view starts moving with your finger (using using translateY/X or setY/X), the velocity is completely random (I think the velocity is calculated using the view's position?). Does anyone have any suggestions for getting an accurate velocity of your movement when swiping a view?
Notes:
I am using the touch events from my View's onTouchListener for Velocity tracking.
Cheers
Answer: You should keep track of how much the view has been moved and call MotionEvent.offsetLocation to "fix" the event coordinates before passing it to a VelocityTracker.
private float mLastX;
private float mTranslationX;
private VelocityTracker mTracker;

@Override
public boolean onTouch(final View view, MotionEvent motionEvent) {
  motionEvent.offsetLocation(mTranslationX, 0);

  switch (motionEvent.getActionMasked()) {
    case MotionEvent.ACTION_DOWN:
      mLastX = motionEvent.getRawX();
      mTracker = VelocityTracker.obtain();
      mTracker.addMovement(motionEvent);
      return true;

    case MotionEvent.ACTION_MOVE:
      mTranslationX += motionEvent.getRawX() - mLastX;
      view.setTranslationX(mTranslationX);
      mTracker.addMovement(motionEvent);
      return true;

    case MotionEvent.ACTION_UP:
      // get your correct velocity from mTracker
      ...
  }
}

Check out the documentation for MotionEvent.getRawX / Y too.
They return the X/Y coordinates of the pointer relative to the entire screen, therefore they aren't affected by the movement of whatever View you're listening on.
Answer: The simplest way deals with absolute coordinates write:
motionEvent.setLocation(e.getRawX(), e.getRawY());
Comment: If you expect the MotionEvent to be used elsewhere, make a copy of it first, using MotionEvent.obtain().
Answer: Assuming you aren't scaling, the velocity of a touch is the amount your finger has moved, divided by the time.  Time is easy to get-  just request the system time in milliseconds on each event and subtrace.  For a translated view, you want to make sure that you use the same frame of reference.  Basically keep track of the x and y offset of the view set by translating it, and add the offset of the touch to it to get the total offset of your finger relative to origin.  Only compare those numbers for your velocity tracking.
If you're scaling the view as well, it gets more complicated.  You need to do the same kind of math with the scaling factor.  Basically you're translating all points into the same reference system.q
Comment: OK. That does sound pretty easy. I was hoping to use the VelocityTracker class and have it done for me, but maybe I will just implement it myself as you say.
Answer: I think you are talking about the camera movement, like following an athlete in real time.
If so, there is only one way: During the capture of the movement you need a fixed point, like a tennis ball in the ground to subtract the velocity of the static ball to "one joint" in the athlete.
To do this is necessary to obtain the X, Y coordinates in the initial and final frame of the static object to make the difference to the moving object.
Moving object:  Square((X position final-X position initial)^2 + (Y position final-Y position initial)^2 )
then convert pixels to meters or miles
then divide the result by seconds (also need a convertion from miliseconds)
you get km/h and mp/h for the moving object.
Do all steps for the static object.
Subtract the result from the static object to the moving object.
The same applies to zoom operations.
All the operations are manual. If you want the real velocity in real time you need automatic tracking not suitable for android. In soccer, using 4 cameras you need quadprocessors with minimum 3000Mhz. I advice to use Matlab.

Track the velocity of a moving view


openldap - adding image to 'photo' attribute gives me 'no validator for syntax'

Question: New to openLDAP - i'm trying to simply add a base64 encoded binary (16Kb) image to the photo attribute to the person objectClass but whatever i try i simply get this error 'no validator for syntax 18.104.22.168.4.1.14220.127.116.11.23'.
Also changing the ldif to stream the binary image (using photo: <file:///tmp/t1.png) also fails with the same error.
I've tried with Apache Directory studio (that takes the binary file and converts it to the base64 representation) but fails with the same error. I'm able to get this working 'with the same base64 text' against the jpegPhoto attribute (so this suggests the encoding is well formed) BUT i would simply like understand why it failed for the photo attribute - anyone able to explain? This is a fresh install against the latest OpenLDAP on Centos.
googling this error gives me Googlewack.
Comment: Is it base64 encoded? https://stackoverflow.com/questions/5829590/edit-ldap-photo-attribute-spring-ldap-invalidattributevalueexception/5829880#5829880
Comment: @GregAskew - it is yes, i've expanded the question to make that back much clearer
Answer: Every LDAP server is configured with a schema where each LDAP attribute has a specific "syntax". They are not all defined as arbitrary strings or blobs – they need to conform to their syntax, which the LDAP server tries to validate.
The photo attribute was originally defined to have an image specifically in the CCITT "Group 3 Fax" image format – that's what the syntax OID in question means.
(That's why jpegPhoto is a separate attribute – it was added later in order to maintain compatibility with older directories and clients, as changing the data type of an existing 'photo' field wouldn't have been a good idea.)
Currently you're getting the error message because the OpenLDAP server doesn't really support this data format at all, but if it did, you'd still be getting a different message about the (JPEG) data not being recognized as G3Fax image data.
You could edit the attribute's OpenLDAP schema to change the data type it accepts (via cn=config) or you could continue using the newer 'jpegPhoto' attribute.
Comment: Yeah, that's like migrating from MySQL to Postgres – the concepts are the same but the implementation is going to differ. ApacheDS might have a different schema definition for this attribute, it will have different implementation of attribute syntax handling, etc.
Comment: i think my confusion (that i didn't talk about in the question) is that i'm migrating from apache DS to openLDAP and it didn't complain about images in this attribute..


openpyxl load_workbook TypeError:sequence item 2: expected str instance, NoneType found

Question: I want to transfer the data from one xlsx file to another xlsx file, so I write this:
from openpyxl import load_workbook

wb_source = load_workbook('test.xlsx')
wb_target = load_workbook('template.xlsx',keep_vba=True)

but seems second load doesn't work:
TypeError                                 Traceback (most recent call last)
<ipython-input-1-f9200c00961e> in <module>()
      2
      3 wb_source = load_workbook('test.xlsx') #Get the current Active Sheet
----> 4 wb_target = load_workbook('template.xlsx',keep_vba=True)
      5 #based on sheet name
      6 #ws_source = wb_source.get_sheet_by_name("raw-74126")

C:\Anaconda3\lib\site-packages\openpyxl\reader\excel.py in load_workbook(filename, read_only, use_iterators, keep_vba, guess_types, data_only)
    190         if strings_path.startswith("/"):
    191             strings_path = strings_path[1:]
--> 192         shared_strings = read_string_table(archive.read(strings_path))
    193     else:
    194         shared_strings = []

C:\Anaconda3\lib\site-packages\openpyxl\reader\strings.py in read_string_table(xml_source)
     19         if node.tag == '{%s}si' % SHEET_MAIN_NS:
     20
---> 21             text = Text.from_tree(node).content
     22             text = text.replace('x005F_', '')
     23             strings.append(text)

C:\Anaconda3\lib\site-packages\openpyxl\cell\text.py in content(self)
    183         for block in self.formatted:
    184             snippets.append(block.t)
--> 185         return "".join(snippets)

TypeError: sequence item 2: expected str instance, NoneType found

The target one is I save as from a xlsm file, could you guys help me to see what happens?
Comment: Welcome to SO! See the [tour] and [ask].
Comment: Which version of openpyxl are you using?
Comment: the version 2.3.2
Answer: It is necessary to update module openpyxl to 2.4.2


Why does a string instrument get out of tune when a string breaks?

Question: Usually, when a string breaks on my guitar/bass, the remaining strings get out tune. Why does that happen?
Answer: Because the tension changed and the neck might bend a little back, causing the remaining strings to get out of tune (I suppose you notice the pitch a bit higher)
Comment: And if your guitar has a floating bridge the problem is exacerbated as the lowered tension on the bridge means the other strings get raised in pitch, in some cases by quite a large amount


Campo DateTime é nulo ao passar para o controller

Question: Eu tenho em minha aplicação um formulário de pesquisa usando AjaxBeginForm.
No mesmo eu possuo um campo data (DateTime), e no qual eu estou usando o bootstrap datePicker.
Meu form está assim:
                            @using (Ajax.BeginForm("Index", "Pedido", new AjaxOptions { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "divPedidos" }, new { @class = "form-inline" }))
                            {
                                @Html.TextBox("pesquisarRascunhoId", 0, new { style = "display: none" })

Data emissão

                                            @Html.EditorFor(model => model.PedidoFilter.EmissaoInicial, new { htmlAttributes = new { @class = "form-control input-sm datepicker" } })

                                        a

                                            @Html.EditorFor(model => model.PedidoFilter.EmissaoFinal, new { htmlAttributes = new { @class = "form-control input-sm datepicker" } })

                                        <button type="submit" class="btn btn-success">Pesquisar</button>

                            }

Meu javaScript para formatar a minha data em dd/mm/yyyy está assim:
$(".datepicker").datepicker({
        format: "dd/mm/yyyy",
        language: "pt-BR",
        autoclose: true
    });

Minha entidade está assim:
public class PedidoFilter
{
    public DateTime? EmissaoInicial { get; set; }
    public DateTime? EmissaoFinal { get; set; }
}

E por fim meu controller está assim:
    public ActionResult Index(PedidoResult pedidoResult,
    {
        var pedido = _service.FindAll(pedidoResult.PedidoFilter);

        return View(pedido);
    }

1 - Todos os campos do meu formulário chegam no meu controller, porém meus campos de data são sempre nulos, no formato dd/mm/yyyy, que define no meu js do datepicker.
2 - Se eu inserir uma data no formato mm/dd/yyyy ela é passada para o meu controller.
Minha pergunta é:
Como posso passar meu campo de data no formato dd/mm/yyyy e recebe-los em meu controller, sem que os mesmos sejam nulos?
Comment: Você só precisa trocar a cultura da aplicação. Você está usando Owin ou as configurações estão no global.asax?
Comment: Não estou usando Owin. Eu define minha cultura no meu web config: ****
Answer: Acredito que pode ser o mesmo problema que tive a pouco tempo, quando eu ia enviar o valor ele barrava pelo fato do formato ser diferente.
Você poderia fazer desta forma:
$(Element).val().split('/').reverse().join('/');

Isso eu acredito que resolve o seu problema.
Comment: Isso não funciona pra mim


C# Convert ArrayList Custom Sort to Generic List Custom Sort

Question: I have an ArrayList of objects that I need to sort in two different fashions, depending on the situation.  I followed this example: http://codebetter.com/blogs/david.hayden/archive/2005/03/06/56584.aspx on how to create a PersonComparer by overloading the IComparer object.  I liked this method because it allowed me to build an enumerator of sort criteria that I could set on the fly.
However, when I convert my ArrayList to the generic List<T> type, this method no longer works.  When I try to pass my "comparer" object, I get the following error:
"The best overloaded method match for 'System.Collections.Generic.List.Sort has some invalid arguments"
My question is: what do I need to change to make this method work?  Or more importantly, is there a better way to create multiple custom sorts using Generic lists?
Comment: You want to implement the IComparer interface in addition to IComparer.  See my comment below.
Answer: List<T>.Sort() takes has an overload that takes an IComparer<T>, List<T>.Sort(IComparer<T>).  IComparer<T> is just like IComparer, but it's strongly typed.
To get your code to compile, you need to change your IComparer implementation to also implement IComparer<T>.  For example, if you have a List<Person>, then your comparer needs to implement IComparer<Person>.  For example:
class Person {
    public string FirstName {get; set;}
    public string LastName {get; set;}
}

// Compares by FirstName then LastName
class PersonComparer : IComparer, IComparer<Person> {
    public int Compare(object x, object y)
    {
        var a = x as Person;
        var b = y as Person;
        return Compare(a, b);
    }

    public int Compare(Person x, Person y)
    {
        var comparisons = new Func<Person, Person, int>[]{
            (a, b) => a.FirstName.CompareTo (y.FirstName),
            (a, b) => a.LastName.CompareTo (y.LastName),
        };
        foreach (var f in comparisons) {
            int c = f (x, y);
            if (c != 0)
                return c;
        }
        return 0;
    }
}

Answer: List.Sort takes one parameter which is a delegate of the following type:
public delegate int Comparison(
    T x,
    T y
)
After looking at the blog post you linked, I find it likely that your method takes two objects of any type.  You should change your method to take two objects of type T (the type of your List).
Example:
Your method probably is something like
int mymethod (object a, object b) {
   // something
}
if your list is a List
then your method should look like this
int mymethod (CustomClass a, CustomClass b) {
   // something
}
Alternatively, it could look like this
int MyMethod2 <T> (T a, T b) {
   // something
}
Comment: This method does not work because in order to overload the IComparer object, you must provide a CompareTo method that accepts two objects.
Comment: I am suggesting that you write a method that with the signature:
int MyMethod2  (T a, T b)

Then, just pass it into the List.Sort method.  Don't make a class that implements IComparer, this method can live anywhere you want it to.
Comment: Alright i'll try that out.  I also fixed the example by changing the implimentations of IComparer to IComparer
Answer: I suggest you look at the LINQ extension methods OrderBy and ThenBy.


Finding the recurrence relation of a known series $\frac{1}{2}+\frac{1}{24}+\frac{1}{720}+...$

Question: If you have a series of numbers (where the first number corresponds to the index zero):
$$ \frac{1}{2}+ \frac{1}{24}+ \frac{1}{720}+... $$
Is there a systematic way to work backwards and find a recurrence relation? Or in other words, something that would be easier for a computer to understand (let's say I wanted to write a program which can take a series of numbers and then compute the relation automatically)
$a_n=...$
Answer: No, since there are infinitely many infinite series that have the same first three terms. It's really a problem in pattern recognition: you're being asked to spot the pattern that the person who posed the question had in mind, which will typically be some fairly simple, regular pattern. Here the expectation is that you will recognize the denominators as factorials, specifically, as $2!,4!$, and $6!$. If you do, it becomes clear that the $k$-th term is $\frac1{(2k+2)!}$. If $a_k$ is the $k$-th term, then
$$a_k=\frac{a_{k-1}}{(2k+1)(2k+2)}\;.$$
Answer: $2!$ $4!$ $6!$ Hmm, do I see a pattern?
Comment: If there were a positive answer to your question, many of us would be out of a job :(
Comment: You've nailed it. I did not see this pattern. I wonder if there is another method besides 'recognizing'? Maybe something that would be more friendly for a computer to understand.
Answer: Don't believe what they tell you, the real answer is
$$
a_n=\frac{1}{337n^2-989n+654}
$$
;-)
P.S. Actually, I can tell you how to write a computer program which will solve all these questions without having to guess anything. This is called Lagrange interpolation. But I doubt that it is the expected answer.
Comment: Wow, look at that, it holds for all $n \ge 1 $...nice. Will have to read up on that. Thank you.
Answer: If course the only valid answer is (2*p)! in the denominators, where p runs through the non-composite positive integers, p=1,2,3,5,7,11,13,... :-)


Getting rid of duplicate links while scraping

Question: Running my script written in python I can see results with bunch of duplicates. Is there any workaround to get rid of this duplicates? Here is my script:
import requests
from lxml import html

def Startpoint():
    default="http://tennishub.co.uk"
    link="http://tennishub.co.uk/"
    response = requests.get(link)
    tree = html.fromstring(response.text)
    titles = tree.xpath('//div[@class="countylist"]')
    for title in titles:
        links = title.xpath('.//a/@href')
        for link in links:
            page = default + link
            Midpoint(page)

def Midpoint(address):
    default="http://tennishub.co.uk"
    response = requests.get(address)
    tree = html.fromstring(response.text)
    titles = tree.xpath('//div[@class="pagination"]')
    for title in titles:
        links = title.xpath('.//a/@href')
        for link in links:
            mlink = default + link
            print(mlink)

Startpoint()

Here is the screenshot of what i'm getting:
Comment: When you scrape a link, add the URL to a `set`. Before scraping a link, check if it's in the set.
Answer: If order is not significant then wrapping set around your links objects will get rid of duplicates since str instances are hashable
links = title.xpath('.//a/@href')
links = set(links)

If you want your links to be unique across all pages then you need to filter out for each title unprocessed links like
import requests
from lxml import html

def Startpoint():
    default = "http://tennishub.co.uk"
    link = "http://tennishub.co.uk/"
    response = requests.get(link)
    tree = html.fromstring(response.text)
    titles = tree.xpath('//div[@class="countylist"]')
    processed_links = set()
    for title in titles:
        unprocessed_links = set(title.xpath('.//a/@href')) - processed_links
        for link in unprocessed_links:
            page = default + link
            Midpoint(page)
        processed_links |= unprocessed_links

def Midpoint(address):
    default = "http://tennishub.co.uk"
    response = requests.get(address)
    tree = html.fromstring(response.text)
    titles = tree.xpath('//div[@class="pagination"]')
    processed_links = set()
    for title in titles:
        unprocessed_links = set(title.xpath('.//a/@href')) - processed_links
        for link in unprocessed_links:
            mlink = default + link
            print(mlink)
        processed_links |= unprocessed_links

Startpoint()

Output (may differ from yours since sets are unordered):
http://tennishub.co.uk/tennis-clubs-by-county/Middlesex/3
http://tennishub.co.uk/tennis-clubs-by-county/Middlesex/10
http://tennishub.co.uk/tennis-clubs-by-county/Middlesex/2
http://tennishub.co.uk/tennis-clubs-by-county/Middlesex/4
http://tennishub.co.uk/tennis-clubs-by-county/Hampshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Hampshire/7
http://tennishub.co.uk/tennis-clubs-by-county/Hampshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Hampshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Oxfordshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Oxfordshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Oxfordshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Buckinghamshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Buckinghamshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Buckinghamshire/5
http://tennishub.co.uk/tennis-clubs-by-county/Buckinghamshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Berkshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Berkshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Berkshire/4
http://tennishub.co.uk/tennis-clubs-by-county/West Sussex/4
http://tennishub.co.uk/tennis-clubs-by-county/West Sussex/3
http://tennishub.co.uk/tennis-clubs-by-county/West Sussex/2
http://tennishub.co.uk/tennis-clubs-by-county/East Sussex/3
http://tennishub.co.uk/tennis-clubs-by-county/East Sussex/2
http://tennishub.co.uk/tennis-clubs-by-county/Kent/8
http://tennishub.co.uk/tennis-clubs-by-county/Kent/3
http://tennishub.co.uk/tennis-clubs-by-county/Kent/4
http://tennishub.co.uk/tennis-clubs-by-county/Kent/2
http://tennishub.co.uk/tennis-clubs-by-county/Surrey/3
http://tennishub.co.uk/tennis-clubs-by-county/Surrey/4
http://tennishub.co.uk/tennis-clubs-by-county/Surrey/2
http://tennishub.co.uk/tennis-clubs-by-county/Surrey/14
http://tennishub.co.uk/tennis-clubs-by-county/Suffolk/2
http://tennishub.co.uk/tennis-clubs-by-county/Suffolk/3
http://tennishub.co.uk/tennis-clubs-by-county/Bedfordshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Hertfordshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Hertfordshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Hertfordshire/7
http://tennishub.co.uk/tennis-clubs-by-county/Hertfordshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Cambridgeshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Cambridgeshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Cambridgeshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Norfolk/2
http://tennishub.co.uk/tennis-clubs-by-county/Norfolk/3
http://tennishub.co.uk/tennis-clubs-by-county/Essex/4
http://tennishub.co.uk/tennis-clubs-by-county/Essex/2
http://tennishub.co.uk/tennis-clubs-by-county/Essex/7
http://tennishub.co.uk/tennis-clubs-by-county/Essex/3
http://tennishub.co.uk/tennis-clubs-by-county/Cheshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Cheshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Cheshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Cheshire/7
http://tennishub.co.uk/tennis-clubs-by-county/Cumbria/2
http://tennishub.co.uk/tennis-clubs-by-county/Lancashire/4
http://tennishub.co.uk/tennis-clubs-by-county/Lancashire/9
http://tennishub.co.uk/tennis-clubs-by-county/Lancashire/3
http://tennishub.co.uk/tennis-clubs-by-county/Lancashire/2
http://tennishub.co.uk/tennis-clubs-by-county/Warwickshire/6
http://tennishub.co.uk/tennis-clubs-by-county/Warwickshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Warwickshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Warwickshire/4
http://tennishub.co.uk/tennis-clubs-by-county/Staffordshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Shropshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Worcestershire/3
http://tennishub.co.uk/tennis-clubs-by-county/Worcestershire/2
http://tennishub.co.uk/tennis-clubs-by-county/South Yorkshire/2
http://tennishub.co.uk/tennis-clubs-by-county/West Yorkshire/3
http://tennishub.co.uk/tennis-clubs-by-county/West Yorkshire/2
http://tennishub.co.uk/tennis-clubs-by-county/West Yorkshire/4
http://tennishub.co.uk/tennis-clubs-by-county/West Yorkshire/5
http://tennishub.co.uk/tennis-clubs-by-county/Northumberland/2
http://tennishub.co.uk/tennis-clubs-by-county/East Yorkshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Durham/2
http://tennishub.co.uk/tennis-clubs-by-county/North Yorkshire/2
http://tennishub.co.uk/tennis-clubs-by-county/North Yorkshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Devon/5
http://tennishub.co.uk/tennis-clubs-by-county/Devon/4
http://tennishub.co.uk/tennis-clubs-by-county/Devon/2
http://tennishub.co.uk/tennis-clubs-by-county/Devon/3
http://tennishub.co.uk/tennis-clubs-by-county/Wiltshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Wiltshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Dorset/2
http://tennishub.co.uk/tennis-clubs-by-county/Dorset/3
http://tennishub.co.uk/tennis-clubs-by-county/Somerset/2
http://tennishub.co.uk/tennis-clubs-by-county/Somerset/4
http://tennishub.co.uk/tennis-clubs-by-county/Somerset/3
http://tennishub.co.uk/tennis-clubs-by-county/Gloucestershire/3
http://tennishub.co.uk/tennis-clubs-by-county/Gloucestershire/4
http://tennishub.co.uk/tennis-clubs-by-county/Gloucestershire/5
http://tennishub.co.uk/tennis-clubs-by-county/Gloucestershire/2
http://tennishub.co.uk/tennis-clubs-by-county/Cornwall/2
http://tennishub.co.uk/tennis-clubs-by-county/Nottinghamshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Nottinghamshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Lincolnshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Derbyshire/2
http://tennishub.co.uk/tennis-clubs-by-county/Derbyshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Leicestershire/3
http://tennishub.co.uk/tennis-clubs-by-county/Leicestershire/2
http://tennishub.co.uk/tennis-clubs-by-county/Leicestershire/4
http://tennishub.co.uk/tennis-clubs-by-county/Northamptonshire/3
http://tennishub.co.uk/tennis-clubs-by-county/Northamptonshire/2

Comment: That gets rid of duplicates within a single page, not across different pages.
Answer: Here is another way of achieving the same:
import requests
from lxml.html import fromstring

base = "http://tennishub.co.uk{}"
link = "http://tennishub.co.uk/"

unique_links = set()

def fetch_links(link):
    r = requests.get(link)
    tree = fromstring(r.text)
    for title_link in tree.xpath('//*[@class="countylist"]//a[@href]/@href'):
        yield base.format(title_link)

def fetch_all_next_page_links(link):
    r = requests.get(link)
    tree = fromstring(r.text)
    for item_link in tree.xpath('//*[@id="content"]/*[@class="pagination"]//a/@href'):
        qualified_link = base.format(item_link)
        if qualified_link not in unique_links:
            yield qualified_link
        unique_links.add(qualified_link)

if __name__ == '__main__':
    for item in fetch_links(link):
        for elem in fetch_all_next_page_links(item):
            print(elem)


SQL/ Postgresql How to group on column but find the average of another column based on certain conditions

Question: I have an existing table called sites which have one or more entries with the same site_id.
I need to create a new table with the following criteria:
1) If there is more than one entry with the same site_id, I have to check the azimuth values of both the entries with the same site_id and if the difference is less than 10, then get an average of the azimuth value and a single entry is created in the new table for them. (see site_id 5 in the existing table which gets id 6 in the new table)
2) if the 2 entries for the same site_id are more than 10 degrees, then each get a different id in the new table. (See site_id 4 in the existing table which get 2 id's 4 and 5 in the new table)
3) All the other entries which have distinct site_id can be copied over as is and each gets a new id in the new table. (All site_ids except 4 and 5 in the existing table)
EXISTING TABLE SITES:
            site_id azimuth longitude latitude
            ------- ------- --------- ---------
            1       10     -10.93    10.22
            2       20      5.937    60.43
            3       30     -7.942    53.47
            4       70      57.94    13.14  ---> A) Difference of more than 10 degrees with entry below
            4       10      57.94    13.14  ---> A) Difference of more than 10 degrees with entry above

            5       45     -7.92     56.88 --> B) Diff of less than 10 deg with below entry
            5       55     -7.92     56.88 --> B) Diff of less than 10 deg with above entry

EXPECTED TABLE with additional id column :
            id      site_id azimuth longitude latitude
            ------- ------- ------- --------- ---------
             1         1       10     -10.93    10.22
             2         2       20      5.937    60.43
             3         3       30     -7.942    53.47

             4         4       70      57.94    13.14  // A) Since the difference in azimuth between the 2 entries in above table is more than 10 degrees, each entry goes as separate entries in the new table

             5         4       10      57.94    13.14   // A) Since the difference in azimuth between the 2 entries in above table is more than 10 degrees, each entry goes as separate entries in the new table

             6         5       50     -7.92     56.88   // B) The azimuth was within 10 degrees with the other entry, so the average of 45+55/2=50 is taken as azimuth for site_id 5

Since I have to find the average of azimuths based on the 10 degree difference criteria, my aggregate GROUP BY does not work for all entries.
I'm a novice at SQL and would appreciate any help I can get on this.
Comment: What if there are more than two entries?
Comment: If there are more than 2 entries with the same site_id, then the maxAzimuthDifference between any 2 entries within the same site_id should not exceed 20 degrees. Else all of them get a different id in the new table.
Comment: . . I would recommend asking a *new* question with that information, after you have accepted an answer to this one.
Answer: This is a complicated question.  One approach is to use window functions to gather all the available information into potential columns.  Then, use simple filtering to determine which columns to take:
select site_id,
       (case when max_azimuth - min_azimuth < 10 then avg_azimuth
             else azimuth
        end) as azimuth, longitude, latitude
from (select site_id, azimuth, longitude, latitude,
             row_number() over (partition by site_id) as seqnum,
             count(*) over (partition by site_id) as cnt,
             avg(azimuth) over (partition by site_id) as avg_azimuth,
             min(azimuth) over (partition by site_id) as min_azimuth,
             max(azimuth) over (partition by site_id) as max_azimuth
      from sites site_id
     ) t
where cnt = 1 or
      (seqnum = 1 and (max_azimuth - min_azimuth) < 10) or
      (max_azimuth - min_azimuth) >= 10;

Comment: Hi Gordon,Thanks for your quick reply. If I run the query you mentioned in your reply, I only get entries for site_id 1,2 and 3.  There are no entries for either of the duplicate site_id 4 and 5. Not sure if I'm missing something here.
Answer: We can do this in a two-step process:

Step 1: create a table grouping by site_id that determines if the sites with that site_id should be combined or not
Step 2: join this with the original table to pull in the non-combined data where necessary

The result is the below:
select row_number() over () AS id
 , s2.site_id
 , case when t.close_azimuths then avg_azimuth else s2.azimuth end as azimuth
 , s2.longitude
 , s2.latitude
from
  (select site_id
   , max(azimuth) - min(azimuth) <= 10 as close_azimuths
   , avg(azimuth) as avg_azimuth
  from sites
  group by site_id ) t
join sites s2 on s2.site_id = t.site_id

group by s2.site_id
 , case when t.close_azimuths then avg_azimuth else s2.azimuth end
 , s2.longitude
 , s2.latitude

Note that the new azimuth column is not an integer, since it is an average of the integer rows. If the azimuth reading should be an integer you can round and coerce back to integer with ::integer


TabBar is not showing [More…] icon while loading tabItems dynamically from view controller

Question: Here i am adding tab items dynamically but its showing only 4 items ( More... tab item is missing). I have gone through a lot of articles and stackOverFlow posts but failed to find any appropriate solution. Here is my code so far...
<code>override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    loadDynamicItems()
}

func loadDynamicItems()  {

    let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
    var controllerArray = [UIViewController]()

    for i in 1...8 {
        let controller = storyBoard.instantiateViewController(withIdentifier: "newsCollection") as! NewsVC
        let tabIcon = UIImage.fontAwesomeIcon(name: .addressBook,
                                              textColor: UIColor.black,
                                              size: CGSize(width: 30, height: 30))

        controller.tabBarItem = UITabBarItem(title: "item \(i)", image: tabIcon, tag: i)
        controllerArray.append(controller)
    }

    self.setViewControllers(controllerArray, animated: true)
}
</code>
But result seems like this IMAGE
why Its showing only 4 items!
It should load a [More...] button as fifth child from where i can access the rest of the items.
But why its not there !?
Comment: I think you have to use UITabController and NOT UIViewController. Look this tutorial: http://geekyviney.blogspot.com.es/2015/02/programmatically-designing.html
Comment: Why does you `for` loop, loop through 8 items when you only need 5 tab bar items?
Comment: where does call this method ?
Comment: try this in appdelegate : http://stackoverflow.com/a/15383967/3901620
Answer: When using a Storyboard, in order to add a TabBarController to your application you need to drag and drop a UITabBarViewController instead of a plain UIViewController. Otherwise some properties are not correctly derived (like the TabBar - please see my screenshot).
Just make sure you delete the automatically created TabBar items!


SharePoint on line Analytic report

Question: When gnerate Auditing Reports for a site collection on our SharePoint tenant for 8 months from the begining of year till now -form Jan to August- it display two months only May and June.
Any one can help me on solving this issue?
Answer: I can not reproduce the issue in my SharePoint.
Whether you use audit logs in the site collection or Security & Compliance Center?
I suggest you get audit logs in the Security & Compliance Center or through PowerShell.
Reference:
SharePoint Online: How to View Audit Log Reports in Security & Compliance Center?

SharePoint on line Analytic report


Reduce quintic equation

Question: If we have the general quintic equation
$$ax^5+bx^4+cx^3+dx^2+ex+f=0$$
we can vanish the quartic term by doing the substitution $x=y-b/5a$. The question I wanna ask is if there is a possible way to do a substitution so the quarticc and the quadratic term is vanished so that we are left with the equation
$$ay^5+by^3+cy+d=0$$
($a$,$b$,$c$,$d$ not the same of course)
Thank you for your time.
If someone can fix the latex it would be great, thank you.
Comment: It's possible to reduce quintic equations to [Bring Quintic Form](http://mathworld.wolfram.com/BringQuinticForm.html) which has a quintic term, but then just a linear term.
Comment: I don't know if it's any help, but Mathematica is also doing research in this kind of subject: http://library.wolfram.com/examples/quintic/main.html
Comment: Thank you for the information. I am pretty sure that there is no such substitution cause if there was, then the quintic would be solvable, which has been proved to be impossible.
Comment: @user154129 Sure. This is generally known to us as the [Brioschi quintic form](http://mathworld.wolfram.com/BrioschiQuinticForm.html)
Answer: Let us see directly why this is impossible. I divide through by $a$ (or equivalently, consider $a = 1$) for ease of notation.
We start with $x^5 + bx^4 + cx^3 + dx^2 + ex + f$, and we will be doing a substitution $x \mapsto x - \lambda$. Let's see what constraints we get from wanting to remove the quartic term. So we collect the coefficients of $x^4$.
The $x^5$ term gives us $-5\lambda x^4$, and the $bx^4$ term gives us $bx^4$ (i.e. it doesn't change). We want these to cancel, so we want $bx^4 - 5\lambda x^4 = 0$, or for $\lambda = \frac{b}{5}$. This is completely forced, and no other substitution will remove the quartic term in general.
So doing any other substitution will not remove the quartic term, and this substitution does not in general remove the quadratic term (which I do not show, because it's an annoying computation - alternatively, choose just about any quintic and it will give a counterexample).
So the answer is no, it is not possible to do a generic substitution such that both the quartic and quadratic terms vanish.
Comment: It depends on what transformations you allow. I was assuming you wanted a linear shift, as was stated by $x \mapsto x - \lambda$. Tshirnhausen transformations are much more complicated. More on those can be found in [this post](http://math.stackexchange.com/a/542228/9754).
Comment: This answer and Peter Woolfit's comment seem to be contradictory. It would be helpful to explain why they are not.
Comment: @mixedmath I think you meant something else. It's possible to do a transformation that will reduce a general quintic to the required form, which will essentially be a _rational_ transformation rather than linear. But "it is not possible to do a generic substitution" is a confusing statement.

Reduce quintic equation


Android childbrowser plugin with cordova 2.3.0 giving error message

Question: I have successfully integrated android childbrowser plugin in cordova 1.9.0. Now i want to use same childbowser plugin in cordova 2.3.0. I have downloaded recent(Updated) child browser plugin and made some modification according to cordova 2.3.0 requirement, but still  getting one error at line no 411 i.e "The method success(PluginResult, String) is undefined for the type ChildBrowser".
This is where i am getting error message i.e

this.success(result, this.browserCallbackId);

Below is the error causing method.
<code> private void sendUpdate(JSONObject obj, boolean keepCallback) {
        if (this.browserCallbackId != null) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
            result.setKeepCallback(keepCallback);
            **this.success(result, this.browserCallbackId);**
        }
    }
</code>
Any one suggest what should i do to remove error message and code to work properly.
Below is the modified whole code
<code>/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2011, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
*/
package com.nxtwhat.SuvilasCDV23;

import java.io.IOException;
import java.io.InputStream;

import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class ChildBrowser extends CordovaPlugin  {

    protected static final String LOG_TAG = "ChildBrowser";
    private static int CLOSE_EVENT = 0;
    private static int LOCATION_CHANGED_EVENT = 1;

    private String browserCallbackId = null;

    private Dialog dialog;
    private WebView webview;
    private EditText edittext;
    private boolean showLocationBar = true;

    /**
* Executes the request and returns PluginResult.
*
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message.
*/
    public PluginResult execute(String action, JSONArray args, String callbackId) {
        PluginResult.Status status = PluginResult.Status.OK;
        String result = "";

        try {
            if (action.equals("showWebPage")) {
                this.browserCallbackId = callbackId;

                // If the ChildBrowser is already open then throw an error
                if (dialog != null && dialog.isShowing()) {
                    return new PluginResult(PluginResult.Status.ERROR, "ChildBrowser is already open");
                }

                result = this.showWebPage(args.getString(0), args.optJSONObject(1));

                if (result.length() > 0) {
                    status = PluginResult.Status.ERROR;
                    return new PluginResult(status, result);
                } else {
                    PluginResult pluginResult = new PluginResult(status, result);
                    pluginResult.setKeepCallback(true);
                    return pluginResult;
                }
            }
            else if (action.equals("close")) {
                closeDialog();

                JSONObject obj = new JSONObject();
                obj.put("type", CLOSE_EVENT);

                PluginResult pluginResult = new PluginResult(status, obj);
                pluginResult.setKeepCallback(false);
                return pluginResult;
            }
            else if (action.equals("openExternal")) {
                result = this.openExternal(args.getString(0), args.optBoolean(1));
                if (result.length() > 0) {
                    status = PluginResult.Status.ERROR;
                }
            }
            else {
                status = PluginResult.Status.INVALID_ACTION;
            }
            return new PluginResult(status, result);
        } catch (JSONException e) {
            return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
    }

    /**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param usePhoneGap Load url in PhoneGap webview
* @return "" if ok, or error message.
*/
    public String openExternal(String url, boolean usePhoneGap) {
        try {
            Intent intent = null;
            if (usePhoneGap) {
                intent = new Intent().setClass(this.cordova.getActivity(), org.apache.cordova.DroidGap.class);
                intent.setData(Uri.parse(url)); // This line will be removed in future.
                intent.putExtra("url", url);

                // Timeout parameter: 60 sec max - May be less if http device timeout is less.
                intent.putExtra("loadUrlTimeoutValue", 60000);

                // These parameters can be configured if you want to show the loading dialog
                intent.putExtra("loadingDialog", "Wait,Loading web page..."); // show loading dialog
                intent.putExtra("hideLoadingDialogOnPageLoad", true); // hide it once page has completely loaded
            }
            else {
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(url));
            }
            this.cordova.getActivity().startActivity(intent);
            return "";
        } catch (android.content.ActivityNotFoundException e) {
            Log.d(LOG_TAG, "ChildBrowser: Error loading url "+url+":"+ e.toString());
            return e.toString();
        }
    }

    /**
* Closes the dialog
*/
    private void closeDialog() {
        if (dialog != null) {
            dialog.dismiss();
        }
    }

    /**
* Checks to see if it is possible to go back one page in history, then does so.
*/
    private void goBack() {
        if (this.webview.canGoBack()) {
            this.webview.goBack();
        }
    }

    /**
* Checks to see if it is possible to go forward one page in history, then does so.
*/
    private void goForward() {
        if (this.webview.canGoForward()) {
            this.webview.goForward();
        }
    }

    /**
* Navigate to the new page
*
* @param url to load
*/
    private void navigate(String url) {
        InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);

        if (!url.startsWith("http") && !url.startsWith("file:")) {
            this.webview.loadUrl("http://" + url);
        } else {
            this.webview.loadUrl(url);
        }
        this.webview.requestFocus();
    }

    /**
* Should we show the location bar?
*
* @return boolean
*/
    private boolean getShowLocationBar() {
        return this.showLocationBar;
    }

    /**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param jsonObject
*/
    public String showWebPage(final String url, JSONObject options) {
        // Determine if we should hide the location bar.
        if (options != null) {
            showLocationBar = options.optBoolean("showLocationBar", true);
        }

        // Create dialog in new thread
        Runnable runnable = new Runnable() {
            /**
* Convert our DIP units to Pixels
*
* @return int
*/
            private int dpToPixels(int dipValue) {
                int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
                                                            (float) dipValue,
                                                            cordova.getActivity().getResources().getDisplayMetrics()
                );

                return value;
            }

            public void run() {
                // Let's create the main dialog
                dialog = new Dialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
                dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                dialog.setCancelable(true);
                dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        public void onDismiss(DialogInterface dialog) {
                            try {
                                JSONObject obj = new JSONObject();
                                obj.put("type", CLOSE_EVENT);

                                sendUpdate(obj, false);
                            } catch (JSONException e) {
                                Log.d(LOG_TAG, "Should never happen");
                            }
                        }
                });

                // Main container layout
                LinearLayout main = new LinearLayout(cordova.getActivity());
                main.setOrientation(LinearLayout.VERTICAL);

                // Toolbar layout
                RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
                toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, this.dpToPixels(44)));
                toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
                toolbar.setHorizontalGravity(Gravity.LEFT);
                toolbar.setVerticalGravity(Gravity.TOP);

                // Action Button Container layout
                RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
                actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
                actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
                actionButtonContainer.setId(1);

                // Back button
                ImageButton back = new ImageButton(cordova.getActivity());
                RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
                back.setLayoutParams(backLayoutParams);
                back.setContentDescription("Back Button");
                back.setId(2);
                try {
                    back.setImageBitmap(loadDrawable("www/childbrowser/icon_arrow_left.png"));
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.getMessage(), e);
                }
                back.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        goBack();
                    }
                });

                // Forward button
                ImageButton forward = new ImageButton(cordova.getActivity());
                RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
                forward.setLayoutParams(forwardLayoutParams);
                forward.setContentDescription("Forward Button");
                forward.setId(3);
                try {
                    forward.setImageBitmap(loadDrawable("www/childbrowser/icon_arrow_right.png"));
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.getMessage(), e);
                }
                forward.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        goForward();
                    }
                });

                // Edit Text Box
                edittext = new EditText(cordova.getActivity());
                RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
                textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
                textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
                edittext.setLayoutParams(textLayoutParams);
                edittext.setId(4);
                edittext.setSingleLine(true);
                edittext.setText(url);
                edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
                edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
                edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
                edittext.setOnKeyListener(new View.OnKeyListener() {
                    public boolean onKey(View v, int keyCode, KeyEvent event) {
                        // If the event is a key-down event on the "enter" button
                        if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
                          navigate(edittext.getText().toString());
                          return true;
                        }
                        return false;
                    }
                });

                // Close button
                ImageButton close = new ImageButton(cordova.getActivity());
                RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                close.setLayoutParams(closeLayoutParams);
                forward.setContentDescription("Close Button");
                close.setId(5);
                try {
                    close.setImageBitmap(loadDrawable("www/childbrowser/icon_close.png"));
                } catch (IOException e) {
                    Log.e(LOG_TAG, e.getMessage(), e);
                }
                close.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        closeDialog();
                    }
                });

                // WebView
                webview = new WebView(cordova.getActivity());
                webview.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
                webview.setWebChromeClient(new WebChromeClient());
                WebViewClient client = new ChildBrowserClient(edittext);
                webview.setWebViewClient(client);
                WebSettings settings = webview.getSettings();
                settings.setJavaScriptEnabled(true);
                settings.setJavaScriptCanOpenWindowsAutomatically(true);
                settings.setBuiltInZoomControls(true);
                settings.setPluginsEnabled(true);
                settings.setDomStorageEnabled(true);
                webview.loadUrl(url);
                webview.setId(6);
                webview.getSettings().setLoadWithOverviewMode(true);
                webview.getSettings().setUseWideViewPort(true);
                webview.requestFocus();
                webview.requestFocusFromTouch();

                // Add the back and forward buttons to our action button container layout
                actionButtonContainer.addView(back);
                actionButtonContainer.addView(forward);

                // Add the views to our toolbar
                toolbar.addView(actionButtonContainer);
                toolbar.addView(edittext);
                toolbar.addView(close);

                // Don't add the toolbar if its been disabled
                if (getShowLocationBar()) {
                    // Add our toolbar to our main view/layout
                    main.addView(toolbar);
                }

                // Add our webview to our main view/layout
                main.addView(webview);

                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
                lp.copyFrom(dialog.getWindow().getAttributes());
                lp.width = WindowManager.LayoutParams.FILL_PARENT;
                lp.height = WindowManager.LayoutParams.FILL_PARENT;

                dialog.setContentView(main);
                dialog.show();
                dialog.getWindow().setAttributes(lp);
            }

          private Bitmap loadDrawable(String filename) throws java.io.IOException {
              InputStream input = cordova.getActivity().getAssets().open(filename);
              return BitmapFactory.decodeStream(input);
          }
        };
        this.cordova.getActivity().runOnUiThread(runnable);
        return "";
    }

    /**
* Create a new plugin result and send it back to JavaScript
*
* @param obj a JSONObject contain event payload information
*/
    private void sendUpdate(JSONObject obj, boolean keepCallback) {
        if (this.browserCallbackId != null) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
            result.setKeepCallback(keepCallback);
            **this.success(result, this.browserCallbackId);**
        }
    }

    /**
* The webview client receives notifications about appView
*/
    public class ChildBrowserClient extends WebViewClient {
        EditText edittext;

        /**
* Constructor.
*
* @param mContext
* @param edittext
*/
        public ChildBrowserClient(EditText mEditText) {
            this.edittext = mEditText;
        }

        /**
* Notify the host application that a page has started loading.
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            String newloc;
            if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
                newloc = url;
            } else {
                newloc = "http://" + url;
            }

            if (!newloc.equals(edittext.getText().toString())) {
                edittext.setText(newloc);
            }

            try {
                JSONObject obj = new JSONObject();
                obj.put("type", LOCATION_CHANGED_EVENT);
                obj.put("location", url);

                sendUpdate(obj, true);
            } catch (JSONException e) {
                Log.d("ChildBrowser", "This should never happen");
            }
        }
    }
}
</code>
Answer: use the new inappbrowser
http://docs.phonegap.com/en/2.3.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser
This will replace childbrowser
Answer: If you still want to use the Childbrowser, here is the refreshed code: https://github.com/mpeterka/phonegap-plugins/blob/6671b5f2656bd1cd2306367f908282a9c6d56864/Android/ChildBrowser/2.0.0/src/com/phonegap/plugins/childBrowser/ChildBrowser.java


How to disable kubectl insecure approval towards the kube apiserver

Question: I am trying to make my Master Server-API more secure in order to avoid allowing non https requests to go through.
Sample of config:
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    server: https://ip:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
    token: REDACTED

Which works as long as I am using the correct CAs.
My problem is it also works if I remove the CAs or I have wrongly CAs and simply I apply the flag --insecure-skip-tls-verify.
How can I force the server to allow https connections instead of http on the Server-API?
I have also disabled anonymous requests Anonymous requests but I can still see the requests can pass through.
Comment: Could you share more information about your environment? What Kubernetes version are you using? Its your local env? Do you want to use some 3rd party software likne `Nginx Ingress Controller` or you want to use pure Kubernetes way? If you will check [kubernetes docs](https://kubernetes.io/docs/reference/kubectl/kubectl/) you will find description about `--insecure-skip-tls-verify` - `If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure` In short, with this parameter Kubernetes will skip validating CA. In short you want force HTTPS?
Comment: Hello @PjoterS, yes it is a cluster on bare metal. I use ingress and also an external LB that I have configured as ssl pass through for port 6443. You got it exactly right I want to enforce https only not accept http. I do not allow through the LB the port 8080 to pass through but on port 6443 if I use the flag `--insecure-skip-tls-verify` the API accepts the request. How can I stop this and allow only https? Thank you in advance for your time and effort.
Answer:
My problem is it also works if I remove the CAs or I have wrongly CAs and simply I apply the flag --insecure-skip-tls-verify.

Using --insecure-skip-tls-verify is highly NOT RECOMMENDED in production environment. It can be used when you want to do some local tests or for learning purpose.
In Kubectl documentation you have information:
--insecure-skip-tls-verify

If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure

So, if this flag will be set as true, it will always skip certs and identity of server is not checked at all. It's similar to curl -k
-k, --insecure
              (TLS) By default, every SSL connection curl makes is verified to
              The  server  connection  is verified by making sure the server's
              interface name, IP address or host name.

You can secure your cluster in many ways but it depends on scenario. However, there are some main API server ports and IPs concepts:
Use SecurePort
By default the Kubernetes API server serves HTTP on 2 ports:

localhost port:

is intended for testing and bootstrap, and for other components of the master >node (scheduler, controller-manager) to talk to the API
no TLS
Disable insecure http connections:
default is port 8080, change with --insecure-port flag.  (It can be disabled by --insecure-port=0)
default IP is localhost, change with --insecure-bind-address flag. (Remove --insecure-bind-address)
request bypasses authentication and authorization modules.
request handled by admission control module(s).
protected by need to have host access

Secure port:

use whenever possible Enable secure port:
uses TLS. Set cert with --tls-cert-file and key with --tls-private-key-file flag.
default is port 6443, change with --secure-port flag.
default IP is first non-localhost network interface, change with --bind-address flag.
request handled by authentication and authorization modules.
request handled by admission control module(s).
authentication and authorization modules run.

Restrict API access, meaning you should allow access to your api only from specific IP or specific IP range (authorized networks). It shouldn't be accessible from the outside of the world. To do it, you may use firewall rules or Network Policy.
Turn off Anonymouse Requests, which you already did.
You can look into --insecure-port=0, however it should be deprecated in newer versions.
As an additional information, I would advise you to check Kubernetes The Hard Way, especially 3 chapters:
Provisioning Compute Resources, Provisioning the CA and Generating TLS Certificates, Generating Kubernetes Configuration Files for Authentication. You can find there some best practices.
Very good explanation of the Kube API-server flags you can find in this article
Useful links about Cluster Security:
The Basics of Keeping Kubernetes Clusters Secure - How to secure the kube-apiserver
Controlling Access to the Kubernetes API
Kubernetes security best practices
Kubernetes Security 101: Risks and 29 Best Practices
Controlling Access to the Kubernetes API
Accessing Clusters


How to handle rotations based on a quat camera?

Question: I'm having a problem with getting rotations based on mouse movement.
I use a camera class similar to this:
http://hamelot.io/visualization/moderngl-camera/
Here is the code:
#include "Camera.h"

#include <gl/glew.h>

#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <SFML/Window/Keyboard.hpp>
#include <SFML/Window/Mouse.hpp>

Camera::Camera() : _viewportX(0), _viewportY(0), _windowX(1920), _windowY(1080), _lastX(0), _lastY(0), _aspect(1), _nearClip(.001f), _farClip(1000.0f), _cameraHeading(0), _cameraPitch(0), _grab(false)
{
    _cameraType = CameraType::FREE;
    _cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
    _fov = 45.0f;
    _cameraPosDelta = glm::vec3(0);
    _cameraScale = 0.01f;
    _maxPitch = 5;
    _maxHeading = 5;
    _moveCamera = false;

}

Camera::~Camera()
{
}

void Camera::reset()
{
    _cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
}

void Camera::update()
{
    _oldDirection = _cameraDirection;
    _cameraDirection = glm::normalize(_cameraLookAt - _cameraPos);
    // We need to set the matrix state, this is important because lighting won't work otherwise
    glViewport(_viewportX, _viewportY, _windowX, _windowY);

    if (_cameraType == CameraType::ORTHO)
    {
        _projection = glm::ortho(-1.5f * float(_aspect), 1.5f * float(_aspect), -1.5f, 1.5f, -10.0f, 10.0f);
    }
    else
    {
        _projection = glm::perspective(_fov, _aspect, _nearClip, _farClip);
        // Axis for pitch rotation
        glm::vec3 axis = glm::cross(_cameraDirection, _cameraUp);
        // Compute quaternion for pitch based on the camera pitch angle
        glm::quat pitchQuat = glm::angleAxis(_cameraPitch, axis);
        // Determine heading quaternion from the camera up vector and the heading angle
        glm::quat headingQuat = glm::angleAxis(_cameraHeading, _cameraUp);
        // Add the two quats
        glm::quat tempQuat = glm::cross(pitchQuat, headingQuat);
        tempQuat = glm::normalize(tempQuat);
        // Update the direction from the quaternion
        _cameraDirection = glm::rotate(tempQuat, _cameraDirection);
        // add the camera delta
        _cameraPos += _cameraPosDelta;
        // set the lookat matrix to be infront of the camera
        _cameraLookAt = _cameraPos + _cameraDirection * 1.0f;
        // Damping for smooth camera
        _cameraHeading *= 0.5f;
        _cameraPitch *= 0.5f;
        _cameraPosDelta *= 0.8f;
    }
    // compute the mvp
    _view = glm::lookAt(_cameraPos, _cameraLookAt, _cameraUp);
}

void Camera::moveKeyboard()
{
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q))
        processMovement(UP);
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::E))
        processMovement(DOWN);
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        processMovement(LEFT);
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        processMovement(RIGHT);
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        processMovement(FORWARD);
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        processMovement(BACK);

}

void Camera::changePitch(float degrees)
{
    //Check bounds with the max pitch rate so that we aren't moving too fast
    if (degrees < -_maxPitch)
    {
        degrees = -_maxPitch;
    }
    else if (degrees > _maxPitch)
    {
        degrees = _maxPitch;
    }
    _cameraPitch += degrees;

    // Check bounds for cameraPitch
    if (_cameraPitch > 360.0f)
    {
        _cameraPitch -= 360.0f;
    }
    else if (_cameraPitch < -360.0f)
    {
        _cameraPitch += 360.0f;
    }
}

void Camera::changeHeading(float degrees)
{
    //Check bounds with the max Heading rate so that we aren't moving too fast
    if (degrees < -_maxHeading)
    {
        degrees = -_maxHeading;
    }
    else if (degrees > _maxHeading)
    {
        degrees = _maxHeading;
    }
    _cameraHeading += degrees;

    // This controls how the heading is changed if the camera is pointed straight up or down
    // The heading delta direction changes
    if (_cameraPitch > 90 && _cameraPitch < 270 || (_cameraPitch < -90 && _cameraPitch > -270))
    {
        _cameraHeading -= degrees;
    }
    else
    {
        _cameraHeading += degrees;
    }

    // Check bounds for cameraHeading
    if (_cameraHeading > 360.0f)
    {
        _cameraHeading -= 360.0f;
    }
    else if (_cameraHeading < -360.0f)
    {
        _cameraHeading += 360.0f;
    }
}

void Camera::processMouseMovement(sf::RenderWindow& window)
{
    auto mousePos = sf::Mouse::getPosition(window);
    if (_lastX == 0 && _lastY == 0)
    {
        _lastX = _windowX / 2;
        _lastY = _windowY / 2;
    }
    if (mousePos != sf::Vector2i(_lastX, _lastY))
    {
        GLfloat xOffset = (_windowX / 2) - mousePos.x;
        GLfloat yOffset = (_windowY / 2) - mousePos.y;
        xOffset *= _cameraScale;
        yOffset *= _cameraScale;
        if (_moveCamera)
        {
            changeHeading(.08f * xOffset);
            changePitch(.08f * yOffset);
        }
    }
    sf::Mouse::setPosition(sf::Vector2i(_windowX / 2, _windowY / 2), window);
}

void Camera::setMode(CameraType type)
{
    _cameraType = type;
    _cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
}

void Camera::setPosition(glm::vec3 pos)
{
    _cameraPos = pos;
}

void Camera::setLookAt(glm::vec3 pos)
{
    _cameraLookAt = pos;
}

void Camera::setFOV(double fov)
{
    _fov = fov;
}

void Camera::setViewport(int locX, int locY, int width, int height)
{
    _viewportX = locX;
    _viewportY = locY;
    _windowX = width;
    _windowY = height;
    _aspect = static_cast<double>(_windowX) / static_cast<double>(_windowY);
}

void Camera::setClipping(double nearClipDistance, double farClipDistance)
{
    _nearClip = nearClipDistance;
    _farClip = farClipDistance;
}

void Camera::processMouseButtons()
{
    if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
    {
        _moveCamera = true;
    }
    else
    {
        _moveCamera = false;
    }
    if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Right))
    {
        _grab = true;
    }
    else
    {
        _grab = false;
    }
}

CameraType Camera::getMode()
{
    return _cameraType;
}

void Camera::getViewPort(int& locX, int& locY, int& width, int& height)
{
    locX = _viewportX;
    locY = _viewportY;
    width = _windowX;
    height = _windowY;

}

void Camera::getMatrices(glm::mat4& view, glm::mat4& projection)
{
    projection = _projection;
    view = _view;
}

void Camera::processMovement(CameraDirection direction)
{
    if (_cameraType == FREE)
    {
        switch (direction)
        {
        case UP:
            _cameraPosDelta -= _cameraUp * _cameraScale;
            break;
        case DOWN:
            _cameraPosDelta += _cameraUp * _cameraScale;
            break;
        case LEFT:
            _cameraPosDelta -= glm::cross(_cameraDirection, _cameraUp) * _cameraScale;
            break;
        case RIGHT:
            _cameraPosDelta += glm::cross(_cameraDirection, _cameraUp) * _cameraScale;
            break;
        case FORWARD:
            _cameraPosDelta += _cameraDirection * _cameraScale;
            break;
        case BACK:
            _cameraPosDelta -= _cameraDirection * _cameraScale;
            break;
        case DEFAULT:
            break;
        }
    }
}

I'm trying to make a model rotate based on the camera direction (or lookAt). I've done the basics like:
float xRot = glm::dot(_oldDirection.x, _cameraDirection.x);
xRot = acos(xRot);

This gives me the angle of the two vectors, and i plug that into my model rotation:
        model[1][1] *= cos(xRot * (PI / 180));
        model[2][1] *= -sin(xRot * (PI / 180));
        model[1][2] *= sin(xRot * (PI / 180));
        model[2][2] *= cos(xRot * (PI / 180));

The problems i'm facing are:

The model rotates about 7x the amount of a my movements. If i move the mouse 180 degrees, the model will rotate 7 times that amount.
The model locks up if i rotate too much in one direction, to fix it i have to rotate the other direction.
A unrelated problem with the camera class : I'm getting a form of gimbal lock. If i move the mouse very fast downward ( i mean i have to thrust it as hard as i can downward) The screen will turn grey and the screen/camera will lock up. The same happens when i thrust the mouse upwards, I can't I think the sides don't gimbal lock.

If you could link me to any resources or help me out, that would be great, thanks!
Answer: You seem to be calculating a quaternion from heading/pitch/roll angles, which is the wrong order. To use a quaternion for smooth camera movement, the mouse/keyboard/whatever controls continually update a quaternion. When you draw, convert this quaternion into a matrix and use that for the camera orientation. (Quat -> rotation matrix should be part of your 3D maths library.)
Search "Ken Shoemake quaternion" for explanations and sample code.
Hope this helps.
Answer: I've been looking for a good and simple way to implement an exclusively quaternion based camera. Surprisingly I couldn't find any good implementation in glm so here it goes.
principles.
 - accumulate the frame pitch yaw and roll separately.
 - calculate the yaw(x) in world space and the pitch(x) and roll(z) in local(default) space.
void Render::Node::setRotationByXYZ(float inX, float inY, float inZ) {

  x += inX/100;
  y += inY/100;
  z += inZ/100;

  glm::quat qX = normalize(glm::quat(cos(x/2), sin(x/2), 0, 0));
  glm::quat qY = normalize(glm::quat(cos(y/2), 0, sin(y/2), 0));
  glm::quat qZ = normalize(glm::quat(cos(z/2), 0, 0, sin(z/2)));

  glm::quat qXWorld = glm::inverse(glm::quat(1.0,0.0,0.0,0.0))*qX;
  glm::quat q = qXWorld*qZ*qY;

  this->rotation = q;
}

So normally you would convert to matrix and transform by identity matrix, but using the quat identity value works just the same.
If you don't need roll, just omit qZ. This works for me but your multiplication order may differ of course.
This is by far the simplest approach I could come up with, I hope it helps someone else.
Answer: I think what you might find useful is an alternative to glm::lookAt:
void Camera::lookAt(Quaternion rot, Vertex Pos)
{
    view = Matrix<4>();

    Vertex v1 = (rot*Vertex(0.0f,0.0f,1.0f)).normalize(); // forward
    Vertex v2 = (rot*Vertex(0.0f,1.0f,0.0f)).normalize().cross(v1); // up
    Vertex v3 = v1.cross(v2);

    view[0][0] = v2.x;
    view[0][1] = v3.x;
    view[0][2] = v1.x;

    view[1][0] = v2.y;
    view[1][1] = v3.y;
    view[1][2] = v1.y;

    view[2][0] = v2.z;
    view[2][1] = v3.z;
    view[2][2] = v1.z;

    view[3][0] = -v2.dot(Pos);
    view[3][1] = -v3.dot(Pos);
    view[3][2] = -v1.dot(Pos);
    //Comment this out if you aren't using the left hand coordinate system
    view = view.transpose();
}

Massive thanks to joe stevens for mentioning this method: http://joestevens.net/post/20063172257/alternate-view-matrix-construction
I rewrote this for my own purposes, but check out the original by any means.
You can then just feed your camera the Quaternion and its Center position and it will churn out a nice view matrix.
This means that you can simply add your yaw,pitch,roll to the quaternion each time that you rotate, or even better use the quaternion as your source of rotations.


Including JS after the JS specified in theme info file

Question: The goal is to include js files for custom block from custom module after the JS specified in the themes.info file. From the moduleName.module
function moduleName_block_view($delta = ''){
  $block = array();
  switch($delta){
    case 'contact_form':{
                $block['subject'] = '';
                $block['content'] = array(
                    '#markup' => build_contact($delta),
                    '#attached' => array(
                        'js' => array(
                            'http://somepath/0.0.2/contact-0.0.2.min.js' => array(
                                'type' => 'file',
                                'weight' => 1000,
                            ),
                            drupal_get_path('module', 'moduleName').'/js/contact-config.js' => array(
                                'type' => 'file',
                                'weight' => 5,
                            ),
                        ),
                    ),
                );
...
return $block;
}

The weights work for the two JS files within the custom block as specified here. Problem is that, i am unable to make these js files be imported after the js files specified in theme.info file. How to make these file import after the theme js? Thank you for help
Answer: You can specify the #scope attribute to control where the JS gets added. For example, you could place it in the footer, which (more likely than not) would come after your theme's JS:
'#attached' => array(
  'js' => array(
    'http://somepath/0.0.2/contact-0.0.2.min.js' => array(
    'type' => 'file',
      'weight' => 1000,
      'scope' => 'footer',
    ),
    drupal_get_path('module', 'moduleName').'/js/contact-config.js' => array(
      'type' => 'file',
      'weight' => 5,
      'scope' => 'footer',
    ),
  ),
),

Alternatively, you could implement hook_js_alter() to change the 'final' ordering of the JS files added through #attached, drupal_add_js(), .info files, etc.


nginx + apache problem with 443 port

Question: Here is my nginx config for port 443:
server {
    listen           *:443;
    server_name      site.com;

    ssl         on;
    ssl_protocols       SSLv3 TLSv1;
    ssl_certificate     /www/certs/site.com.crt;
    ssl_certificate_key /www/certs/site.com.key;

     access_log /var/log/nginx.site.com-access_log;
    location ~* .(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|tar|wav|bmp|rtf|swf|ico|flv|txt|xml|docx|xlsx)$ {
        root /www/site.com/;
        index index.html index.php;
        access_log off;
        expires 30d;
    }
    location ~ /.ht {
        deny all;
    }
    location / {
        proxy_pass http://127.0.0.1:81/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-for $remote_addr;
        proxy_set_header Host $host;
        proxy_connect_timeout 60;
        proxy_send_timeout 90;
        proxy_read_timeout 90;
        proxy_redirect off;
        proxy_set_header Connection close;
        proxy_pass_header Content-Type;
        proxy_pass_header Content-Disposition;
        proxy_pass_header Content-Length;
    }
}

Question 1: Why am I being asked to enter a PEM pass to the cert? How can I enver the password in the nginx config?
178-162-174-212:/usr/bin# service apache2 restart
Restarting web server: apache2.

178-162-174-212:/usr/bin# service nginx restart
Restarting nginx: Enter PEM pass phrase:
Enter PEM pass phrase:
[emerg]: bind() to 22.214.171.124:443 failed (98: Address already in use)
[emerg]: bind() to 22.214.171.124:443 failed (98: Address already in use)
[emerg]: bind() to 22.214.171.124:443 failed (98: Address already in use)
[emerg]: bind() to 220.127.116.11:443 failed (98: Address already in use)
[emerg]: bind() to 188.8.131.52:443 failed (98: Address already in use)
[emerg]: still could not bind()
nginx.

Question 2: Why is there a conflict on port 443?
Apache config:
NameVirtualHost *:81
Listen 127.0.0.1:81
Listen 999

<IfModule mod_ssl.c>
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
</IfModule>

If I comment out the line "Listen 443" that site.com:443 does not work.
Answer: You have both Apache and nginx configured to listen on port 443.
It looks like your intention is to have nginx take control of that port, so you'll want to remove that configuration from Apache, and restart both services: Apache first, then nginx.  This should allow nginx to bind to port 443 and serve those requests.
As for the certificate passphrase, nginx doesn't support saving the passphrase for des-encrypted private keys in the config file (good for them; the obscurity granted by that is worthless).  Decrypt the private key (and make sure it's only readable by the user that nginx is running as):
mv /www/certs/site.com.key /www/certs/site.com.keyold
openssl rsa -in /www/certs/site.com.keyold -out /www/certs/site.com.key

Comment: Did you restart nginx after apache like @Shane suggested?
Comment: If I remove Listen 443 from apache then 443 port not works

nginx + apache problem with 443 port