问:
Determine if email address is mailing list address or personal email address
right now i am building a feature to determine whether email address is mailing list address/group mail address  or personal email address. My current strategy is using manual annotations by human, then those data is used to determine incoming mail address. Example recruitment@stackoverflow.com, is mailing address so i store name of this email address recruitment and mark as group, so in the future if receive email with name recruitment, i ignore it. Do you have any other solution to build this feature without using dataset that build with manual annotations ? any help would be appreciate

答: It might make sense to use the domain address as a feature, or both names for that matter.  Lots of mailing lists are corporate after all, and lots of personal address come from sites such as Yahoo, Gmail, etc.  Having the additional feature could give you more data on which to create a learning algorithm to categorize mail, such as the Perceptron (https://en.wikipedia.org/wiki/Perceptron).  This approach would still involve manual updates, but it would enable your feature to grow smarter over time.</p>


来源: stackexchange

问:
How do I refer to a specific HTML <form> or web page from within a .js file?
I have a .js file with setCookie() and getCookie() functions which are working fine.  I'm running into a problem when trying to use this same .js file with 2 different web pages.  For example, one page's cookie sets name, room number, and beverage selection, while the other page's cookie sets name, address line 1, address line 2, etc...

Thus, I will need to account for differences in the 2 page's forms in the .js file. I thought that I could reference the particular form I'm addressing by its form name (they have different form names) but that isn't working:

```<code>    if (document.getElementsByTagName("form") == document.getElementsByName("form1"))
    {
      document.cookie = 'Name = ' + userName; 'expires = ' + userExpires;
      document.cookie = 'Room = ' + userPrt1; 'expires = ' + userExpires;
      document.cookie = 'Drink = ' + userPrt2; 'expires = ' + userExpires;
    }
</code>```

Thus, my question is, when I have to add an if statement to handle code specific to one particular form (or one particular web page), how do I do this?

Thank you

EDIT: I'm not really sure this will be helpful, but since it was requested, here is the HTML:

```<code><!doctype html>
<html lang="en">
<head>
<title>Javascript</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="mycss.css"/>
<script type="text/javascript" src="myjs.js"></script>
</head>
<body onLoad="javascript:getCookie();">
<header>
<img src="js.png" width="800" height="135"/>
</header>
<main>
  <h2>JavaScript Cookie Test</h2>
  <br><br>
  <form name="form1" id="form1id" action="javascript:setCookie();">
    Name: <input type="text" name="customer" id="customer" required /><br><br>
    Room: <input type="text" name="roomNumber" id="roomNumber" required /><br><br><br>
    What type of coffee would you like to order?<br><br> <!-- It seems radio input would be better here -->
    <input type="checkbox" name="cbox" value="regular" />Regular<br>
    <input type="checkbox" name="cbox" value="espresso" />Espresso<br>
    <input type="checkbox" name="cbox" value="cappuccino" />Cappuccino<br>
    <input type="checkbox" name="cbox" value="mocha" />Mocha<br>
    <input type="checkbox" name="cbox" value="raspberry" />Raspberry<br><br>
    <input type="submit" name="submit" id="submit" value="Submit" />
  </form>
</main>
</code>```

As I mentioned, everything works fine in terms of setting and getting the cookie, whether my JavaScript is in the HTML file or in a separate .js file.   It's only when I try to add code in the .js file that references a specific  form (or web page) that I do not succeed.

Should I be referencing the web page instead of the form? If so, how would I do this in an if statement? Thank you!

EDIT: I want to add a brief clarification in case it will be helpful.  What I want to know is how to reference the form or web page calling a function in the .js file.  If form1 or index1.html called the setCookie() function, I want to add an if code block.  If form2 or index2.html called the setCookie() function, I want to add a different if code block.  Thank you.

答:
Okay, I finally figured out an answer to this.

HTML:

```<code>  <script type="text/javascript">var formName = "form1"</script>
  <form name="form1" action="javascript:setCookie(formName);">
  insert form code...
  </form>
</code>```

Then, in the .js file:

```<code>  function setCookie(formName)
  {
  insert cookie code...
  }
</code>```

And the form name is passed to the JavaScript page, so I can use it to add cookie code that is specific to form1.

I was hoping to find a way to know which form called the JavaScript page, but I'm starting to think that's not possible, since the question has been posted for 5 days without a resolution.  Fortunately, this resolves the issue just as easily as knowing which form called the JavaScript page.

I appreciate everyone's input.

ContentLicense: CC BY-SA 3.0

Body:
I have a .js file with setCookie() and getCookie() functions which are working fine.  I'm running into a problem when trying to use this same .js file with 2 different web pages.  For example, one page's cookie sets name, room number, and beverage selection, while the other page's cookie sets name, address line 1, address line 2, etc...

Thus, I will need to account for differences in the 2 page's forms in the .js file. I thought that I could reference the particular form I'm addressing by its form name (they have different form names) but that isn't working:

    if (document.getElementsByTagName("form") == document.getElementsByName("form1"))
    {
      document.cookie = 'Name = ' + userName; 'expires = ' + userExpires;
      document.cookie = 'Room = ' + userPrt1; 'expires = ' + userExpires;
      document.cookie = 'Drink = ' + userPrt2; 'expires = ' + userExpires;
    }

Thus, my question is, when I have to add an if statement to handle code specific to one particular form (or one particular web page), how do I do this?

Thank you

EDIT: I'm not really sure this will be helpful, but since it was requested, here is the HTML:

<!doctype html>

<title>Javascript</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="mycss.css"/>

JavaScript Cookie Test

  <form name="form1" id="form1id" action="javascript:setCookie();">
    Name: <input type="text" name="customer" id="customer" required />

    Room: <input type="text" name="roomNumber" id="roomNumber" required />

    What type of coffee would you like to order?

    <input type="checkbox" name="cbox" value="regular" />Regular

    <input type="checkbox" name="cbox" value="espresso" />Espresso

    <input type="checkbox" name="cbox" value="cappuccino" />Cappuccino

    <input type="checkbox" name="cbox" value="mocha" />Mocha

    <input type="checkbox" name="cbox" value="raspberry" />Raspberry

    <input type="submit" name="submit" id="submit" value="Submit" />
  </form>

As I mentioned, everything works fine in terms of setting and getting the cookie, whether my JavaScript is in the HTML file or in a separate .js file.   It's only when I try to add code in the .js file that references a specific  form (or web page) that I do not succeed.

Should I be referencing the web page instead of the form? If so, how would I do this in an if statement? Thank you!

EDIT: I want to add a brief clarification in case it will be helpful.  What I want to know is how to reference the form or web page calling a function in the .js file.  If form1 or index1.html called the setCookie() function, I want to add an if code block.  If form2 or index2.html called the setCookie() function, I want to add a different if code block.  Thank you.

Body:
Okay, I finally figured out an answer to this.

HTML:

  <script type="text/javascript">var formName = "form1"</script>
  <form name="form1" action="javascript:setCookie(formName);">
  insert form code...
  </form>

Then, in the .js file:

  function setCookie(formName)
  {
  insert cookie code...
  }

And the form name is passed to the JavaScript page, so I can use it to add cookie code that is specific to form1.

I was hoping to find a way to know which form called the JavaScript page, but I'm starting to think that's not possible, since the question has been posted for 5 days without a resolution.  Fortunately, this resolves the issue just as easily as knowing which form called the JavaScript page.

I appreciate everyone's input.


问:
How to create an Auto-complete combo-box or text box to filter text containing a string
How do I create an Auto-complete ComboBox or TextBox that filters text based on a string?

For example: if I type an "a" in a TextBox, I only get to see all strings containing an "a".

答: I think your best bet is to override the OnKeyDown(KeyEventArgs e) event, and use the value to filter the ComboBox.AutoCompleteCustomSource. Then as noted above, change the AutoCompleteSource to AutoCompleteSource.ListItems. </p>

ContentLicense: CC BY-SA 2.5


问:
"general" variable in oracle apex
I'm developing an application in Oracle Application Express (APEX).

First page contains list of projects as a tabular report.

Clicking any of the rows forwards to the next page, where records can be edited. I've implemented it with following settings:

Link column: link to custom target

Target: Page in this application

Until this is fine.

My problem is how to pass actual report to the next page?

My table, which is the basis of the report has primary key (ID), and also owner & title combination is unique. Currently ID column is not included in the report.

Also the second page doesn't currently contain field showing ID, as this information isn't important to the users.

I know I could set ID column in report, and create a read only (even hidden) text box in the next page, however I'm looking for a more elegant solution. What is the standard way to solve this?

答:
When you create a target page let's say Page 3
And you create some items, let's say P3_ITEM_1,P3_ITEM_2, etc

You can assign values to each of them through the url in the original page

The complete APEX URL Syntax looks like this:

http://apex.oracle.com/pls/apex/f?p=AppId:PageId:Session:Request:Debug:ClearCache:Params:ParamValues:PrinterFriendly

Let’s take a closer look:

http:// – the protocol, can be http or https
apex.oracle.com – your domain/host/server, whatever you want to call it. Can also be localhost.

/pls – indicates that you are using Oracle HTTP Server with mod_plsql. If you are using APEX Listener or Embedded PL/SQL Gateway this part is obsolete/missing.

/apex – the entry from your dads.conf file (this a file on your application-server or EPG where the target database is configured) – in case of EPG its just one entry pointing to localhost, in case of an OAS you can have multiple entries, each pointing to an other database

/f?p= – procedure “f” is called and parameter “p” is set to the complete rest of the string. Remember: APEX uses mod_plsql. “f” is a public procedure, this is the main entrypoint for APEX. Or you could say: “f” is APEX.

AppId – the number or the Alias of the Application

:PageId – the number or the Alias of the Page

:Session – unique Session ID, can be 0 for Public Pages or empty (then APEX creates a new Session)

:Request – a Request Keyword. This is basically free text, just a string you can specify to react in a process or region condition on. e.g. you could pass the keyword “CREATE” and have a condition on the delete button of your page saying “dont’t display this button if request is CREATE”.
In other words: use the REQUEST to control the behaviour of your page.
When pressing a button, the button sets the REQUEST to the button-value (e.g. SAVE), so that you can control the processes in the page processing (Submit) phase.

:Debug – set to YES (uppercase!) switches on the Debug-Mode which renders debug-messages and timestamps in your Browser window. This helps to detect wrong behaviour of your page or performance issues and everything else. Every other value then YES turns the Debug-Mode off

:ClearCache – you can put a page id or a list of page ids here (comma-separated) to clear the cache for these pages (set session state to null, …). But there is more: RP resets the pagination of reports on the page(s), a collection name deletes the collection, APP clears all pages and application-items, SESSION does the same as APP but for all applications the session-id has been used in.

:Parameters – comma seperated list of page-item names. Good practice is to set only those page-items which are on the page you are going to. Accepts page-items as well as application-items.

:ParamValues – comma separated list of values. Each value is assigned to the corresponding Parameter provided in ParamNameList (first value assigned to first parameter, second value assigned to second parameter, and so on…).
The trick here is not having values which contain either a comma “,” or a colon “:”. Both would lead to side-effects and errors, as APEX gets confused when parsing the URL. Using a comma works, if enclosed by slashes: e.g. \123,89.

:PrinterFriendly – set to YES (uppercase!) switches the page into PrinterFriendly-Mode, uses the Printerfriendly template to render the Page. You can also hide regions or other elements in PrinterFriendly-Mode using the PRINTER_FRIENDLY variable in a condition.

In your case you'd use Params:ParamValues like this:

P3_ITEM_1,P3_ITEM_2:someValue_1,someValue_2

Documentation

Title: "general" variable in oracle apex


问:
Java Multithreading wait for threads to finish
Trying to write a multithreaded java program but running into some issues, my primary multithreaded class works fine but if i call it from main it starts all the threads and moves on to the next function, i need it to not move on untill ALL threads are done. read gets passed file paths read(String, String)

```<code>           Thread one = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 1");
                     read(expiredOneYear, master1);
                     System.out.println("Finished thread 1");
                 }
            });

            Thread two = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 2");
                     read(expiredOneAndQuarterYear, master2);
                     System.out.println("Finished thread 2");
                 }
            });

            Thread three = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 3");
                     read(expiredOneAndHalfYear , master3);
                     System.out.println("Finished thread 3");
                 }
            });

            Thread four = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 4");
                     read(expiredOneAnd3QuarterYear , master4);
                     System.out.println("Finished thread 4");
                 }
            });

            // start threads
            one.start();
            two.start();
            three.start();
            four.start();
</code>```

below is what happens in main

```<code>CSVcompare.run(threadCount, mode, fileLocation);
CSVpattern.run(fileLocation);
</code>```

I don't want CSVpattern.run() to start untill ALL threads in CSVcompare.run() have finished, otherwise it won't have certain data ready for CSVpattern.run()

答:
Add calls to join() at the end of run. the join() method waits for a thread to finish.

```<code>try
{
    one.join();
    two.join();
    three.join();
    four.join();
 }
 catch (InterruptedException e)
 {
     System.out.println("Interrupt Occurred");
     e.printStackTrace();
 }
</code>```

And if you want to ignore interrupts (probably should at least figure out why it was interrupted but this will work)

```<code>boolean done = false;
while (!done)
{
    try
    {
        one.join();
        two.join();
        three.join();
        four.join();
        done = true;
    }
    catch (InterruptedException e)
    {
        // Handle interrupt determine if need to exit.
    }
}
</code>```

https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()

Body:
Trying to write a multithreaded java program but running into some issues, my primary multithreaded class works fine but if i call it from main it starts all the threads and moves on to the next function, i need it to not move on untill ALL threads are done. read gets passed file paths read(String, String)

           Thread one = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 1");
                     read(expiredOneYear, master1);
                     System.out.println("Finished thread 1");
                 }
            });

            Thread two = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 2");
                     read(expiredOneAndQuarterYear, master2);
                     System.out.println("Finished thread 2");
                 }
            });

            Thread three = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 3");
                     read(expiredOneAndHalfYear , master3);
                     System.out.println("Finished thread 3");
                 }
            });

            Thread four = new Thread(new Runnable() {
                 public void run()
                 {
                     System.out.println("Starting thread 4");
                     read(expiredOneAnd3QuarterYear , master4);
                     System.out.println("Finished thread 4");
                 }
            });

            // start threads
            one.start();
            two.start();
            three.start();
            four.start();

below is what happens in main

CSVcompare.run(threadCount, mode, fileLocation);
CSVpattern.run(fileLocation);

I don't want CSVpattern.run() to start untill ALL threads in CSVcompare.run() have finished, otherwise it won't have certain data ready for CSVpattern.run()

Body:
Add calls to join() at the end of run. the join() method waits for a thread to finish.

try
{
    one.join();
    two.join();
    three.join();
    four.join();
 }
 catch (InterruptedException e)
 {
     System.out.println("Interrupt Occurred");
     e.printStackTrace();
 }

And if you want to ignore interrupts (probably should at least figure out why it was interrupted but this will work)

boolean done = false;
while (!done)
{
    try
    {
        one.join();
        two.join();
        three.join();
        four.join();
        done = true;
    }
    catch (InterruptedException e)
    {
        // Handle interrupt determine if need to exit.
    }
}

https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()


问:
Can I use Spring framework for android development?
I'm building my android app and wanted to know if spring framework is fine for android development?  I heard there is spring-android and others but still not sure as why they're better for android development vs spring framework.

So as far as the server side code goes is spring ok to use for android development?

答:
Your backend language is almost entirely irrelevant to a mobile application. You will probably be using a network-based API to communicate between the two, and any backend that can speak your preferred protocol will suffice. These days, JSON over HTTP is a common default choice, and Spring supports it out of the box with literally no configuration required (and makes using OAuth very easy, which is nice for mobile applications), but you could choose any backend you like.

Spring Android is an Android-friendly implementation of a few Spring client features, notably RestTemplate, and entirely agnostic of the backend it's talking to. These days, Retrofit and Volley seem to be more popular choices for Android, and both will work just fine with a Spring backend.


问:
You may have an infinite update loop in a component render function
I'm new to VueJS, I've got warning from Vue,

```<code>[Vue warn]: You may have an infinite update loop in a component render function.
</code>```

When i use V-for variable in V-bind:style, here is an example :
in template :

```<code><div v-for="item in model.items" v-bind:class="test(item.result)">
{{item.id}}
</div>
</code>```

in script :

```<code>data() {
    return {
        accept: false,
        not_accept: false,
    };
},
methods: {
    test(result) {
        if (result == 'accept') {
            this.accept = true;
            this.not_accept = false;
        } else if (result == 'Not accept') {
            this.accept = false;
            this.not_accept = true;
        } else {
            console.log(result);
        }

        return {
            success: this.accept,
            danger: this.not_accept,
        };
    },
},
</code>```

答:
First, I'm not sure why you have not_accept, can't you just use !this.accept in its place?

I'm not 100% sure why you're getting this warning, but here's what I think.

The watcher for v-bind:class is watching for changes to item.result, this.accept and this.not_accept. Any change in those values will cause it to be re-rendered by calling test again. But within test, you're modifying this.accept and this.not_accept, so Vue needs to re-check again if the result has changed because of that, and in doing so it may change this.accept and this.not_accept again, and so on.

The class binding and the data is flawed. class for each of the items will be set to the same thing, but it looks as though you want a custom style for each item depending on item.result. You really shouldn't be modifying any properties of this inside test.

It's hard to give a thorough answer because I'm not completely sure of how your component works and what it should do.

Body:
I'm new to VueJS, I've got warning from Vue,

[Vue warn]: You may have an infinite update loop in a component render function.

When i use V-for variable in V-bind:style, here is an example :
in template :

{{item.id}}

in script :

data() {
    return {
        accept: false,
        not_accept: false,
    };
},
methods: {
    test(result) {
        if (result == 'accept') {
            this.accept = true;
            this.not_accept = false;
        } else if (result == 'Not accept') {
            this.accept = false;
            this.not_accept = true;
        } else {
            console.log(result);
        }

        return {
            success: this.accept,
            danger: this.not_accept,
        };
    },
},


问:
getting NaN when trying to cast string to int
I'm getting some very weird results here. I'm trying to convert a string into a integer. Consider the following code below.

```<code>           //Send back to client.
            io.emit('returned message', {
                'message': message,
                'chatid': chatid,
                'userid': userid
            });
            console.log("Returning the data to chat " + chatid);
</code>```

Which is sending data back to client, the console log looks like this:

Returning the data to the chat '5'

and in the client I have

```<code>alert(typeof msg.chatid);
alert(msg.chatid)
var test = Number(msg.chatid);
alert(typeof test)
alert(test);
</code>```

Which produces the following results

String and '5'
  Number and NaN

Please note I've tried Number() and parseInt()

However, trying to code in Jsfiddle, it works fine. I have no idea why I'm getting NaN. Any ideas?

var num = '5';

alert(Number(num));```

答:
You can use the + to quick convert to Number and provide fallback

var getNum = (n) => (+n) ? +n : -1

var chatid = '5'
var chatidinvalid = '5test'
var chatidnan = NaN

console.log("Returning the data to chat ", getNum(chatid));
console.log("Returning the data to chatidinvalid: ", getNum(chatidinvalid));
console.log("Returning the data to chatidinvalid: ", getNum(chatidnan));```

Body:
I'm getting some very weird results here. I'm trying to convert a string into a integer. Consider the following code below.

           //Send back to client.
            io.emit('returned message', {
                'message': message,
                'chatid': chatid,
                'userid': userid
            });
            console.log("Returning the data to chat " + chatid);

Which is sending data back to client, the console log looks like this:

Returning the data to the chat '5'

and in the client I have

alert(typeof msg.chatid);
alert(msg.chatid)
var test = Number(msg.chatid);
alert(typeof test)
alert(test);

Which produces the following results

String and '5'
  Number and NaN

Please note I've tried Number() and parseInt()

However, trying to code in Jsfiddle, it works fine. I have no idea why I'm getting NaN. Any ideas?

var num = '5';

alert(Number(num));


问:
How to remove_action which is call in class
```<code>class Zopim {
private static $_instance = NULL;
private function __construct()
{
    spl_autoload_register( array( &$this, 'autoload' ) );
    add_action( 'wp_footer', array( 'Zopim_Widget', 'zopimme' ) );
    add_action( 'plugins_loaded', array( &$this, 'load_textdomain' ) );
}
}
</code>```

How i use remove_action to remove below action

```<code>add_action( 'wp_footer', array( 'Zopim_Widget', 'zopimme' ) );
</code>```

from function.php

答:
You can call remove_action on wp_footer:

```<code>remove_action( 'wp_footer', array( 'Zopim', 'zopimme' ) );
</code>```

Depending on when that class is actually called, you may need to pass a priority to tell WordPress to do your remove_action a touch later. Because the class doesn't pass a priority to add_action, it will be called with a default priority of 10. If you set a higher priority, your call will happen later:

```<code>remove_action( 'wp_footer', array( 'Zopim', 'zopimme' ), 11 );
</code>```

Body:
class Zopim {
private static $_instance = NULL;
private function __construct()
{
    spl_autoload_register( array( &$this, 'autoload' ) );
    add_action( 'wp_footer', array( 'Zopim_Widget', 'zopimme' ) );
    add_action( 'plugins_loaded', array( &$this, 'load_textdomain' ) );
}
}

How i use remove_action to remove below action

add_action( 'wp_footer', array( 'Zopim_Widget', 'zopimme' ) );

from function.php

Body:
You can call remove_action on wp_footer:

remove_action( 'wp_footer', array( 'Zopim', 'zopimme' ) );

Depending on when that class is actually called, you may need to pass a priority to tell WordPress to do your remove_action a touch later. Because the class doesn't pass a priority to add_action, it will be called with a default priority of 10. If you set a higher priority, your call will happen later:

remove_action( 'wp_footer', array( 'Zopim', 'zopimme' ), 11 );


问:
What is the difference between invokeMethod and methodMissing?
In Groovy, what are the main differences between the invokeMethod and methodMissing methods, and are there clear guidelines when one should be used over the other?

答:
invokeMethod() seems to be used quite a bit in the decorator pattern Groovy doc when doing custom delegation. For example:

```<code>class TracingDecorator {
    private delegate
    TracingDecorator(delegate) {
        this.delegate = delegate
    }
    def invokeMethod(String name, args) {
        println "Calling $name$args"
        def before = System.currentTimeMillis()
        def result = delegate.invokeMethod(name, args)
        println "Got $result in ${System.currentTimeMillis()-before} ms"
        result
    }
}
</code>```

With that said, def result = delegate.invokeMethod(name, args) can be easily replaced with more modern Groovy idiom def result = delegate."$name"(*args).

Body:
invokeMethod() seems to be used quite a bit in the decorator pattern Groovy doc when doing custom delegation. For example:

class TracingDecorator {
    private delegate
    TracingDecorator(delegate) {
        this.delegate = delegate
    }
    def invokeMethod(String name, args) {
        println "Calling $name$args"
        def before = System.currentTimeMillis()
        def result = delegate.invokeMethod(name, args)
        println "Got $result in ${System.currentTimeMillis()-before} ms"
        result
    }
}

With that said, def result = delegate.invokeMethod(name, args) can be easily replaced with more modern Groovy idiom def result = delegate."$name"(*args).


问:
Why can't 32bit binary process go beyond 4GB limit?
Have experienced out of memory (OOM) issues with 32bit binaries and 32 bit Perl while attempting to load more 2-3GB of data into memory on Linux.

Always wondered why an OS with Demand Paging capabilities , cannot swap out resident pages to disk and load more pages to grow beyond 4GB limitation ?

Probably there would be frequent Page-Faults happening (impacting performance) but should never hit OOM issue ?

答:
32-Bits defines the size of the logical address space. You program can access at most 2**32 bytes of memory at any time.

If you have less than 2**32 bytes of physical memory available to a process, that is when the operating system swaps pages out to disk.

In the old days, when there was more physical memory than address space, (e.g., 16-bit address space and 1MB of memory) it was common for processors to support swapping segments of the address space in the manner that you suggest.


问:
Is this design possible with ConstraintLayout?
I was playing around with ConstraintLayout and I can't guess how to do this simple design using only a ConstraintLayout.

Simple design

Each TextView is centered with its image.

Each image is separated with the previous image with a fixed margin.

All views, treated like a group, are centered horizontally.

I have implemented the design using RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="4dp">

        <RelativeLayout
            android:id="@+id/androidALayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/androidAIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidATV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android A"
                android:layout_below="@id/androidAIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidBLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidALayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidBIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidBTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android B"
                android:layout_below="@id/androidBIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidCLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidBLayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidCIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidCTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android C"
                android:layout_below="@id/androidCIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidDLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidCLayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidDIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidDTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android D"
                android:layout_below="@id/androidDIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

    </RelativeLayout>
</RelativeLayout>```

Is this possible?

答:
It surely is possible. The best approach is choosing the first ImageView as reference element to which constrain everything else.

Center the TextView by assigning the left and right constraints to its image left and right edges respectively.

Then assign each image left and top contrain to their right and top edge of the previous image respectively.

Finally select all the images in the layout editor, right click and Center Horizontally (this will chain them to fit the screen width)

Example:

```<code><?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="match_parent">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView"
    app:layout_constraintRight_toRightOf="@+id/imageView"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView" />

<ImageView
    android:id="@+id/imageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="30dp"
    app:layout_constraintRight_toLeftOf="@+id/imageView2" />

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView2"
    app:layout_constraintRight_toRightOf="@+id/imageView2"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView2" />

<ImageView
    android:id="@+id/imageView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView"
    app:layout_constraintTop_toTopOf="@+id/imageView"
    app:layout_constraintRight_toLeftOf="@+id/imageView3" />

<TextView
    android:id="@+id/textView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView3"
    app:layout_constraintRight_toRightOf="@+id/imageView3"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView3" />

<ImageView
    android:id="@+id/imageView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView2"
    app:layout_constraintTop_toTopOf="@+id/imageView2"
    app:layout_constraintRight_toLeftOf="@+id/imageView4" />

<TextView
    android:id="@+id/textView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView4"
    app:layout_constraintRight_toRightOf="@+id/imageView4"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView4" />

<ImageView
    android:id="@+id/imageView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView3"
    app:layout_constraintTop_toTopOf="@+id/imageView3"
    app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>
</code>```

Body:
I was playing around with ConstraintLayout and I can't guess how to do this simple design using only a ConstraintLayout.

Simple design

Each TextView is centered with its image.

Each image is separated with the previous image with a fixed margin.

All views, treated like a group, are centered horizontally.

I have implemented the design using RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="4dp">

        <RelativeLayout
            android:id="@+id/androidALayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/androidAIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidATV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android A"
                android:layout_below="@id/androidAIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidBLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidALayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidBIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidBTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android B"
                android:layout_below="@id/androidBIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidCLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidBLayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidCIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidCTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android C"
                android:layout_below="@id/androidCIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/androidDLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/androidCLayout"
            android:layout_marginLeft="32dp">

            <ImageView
                android:id="@+id/androidDIV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher"
                android:layout_centerHorizontal="true"/>

            <TextView
                android:id="@+id/androidDTV"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Android D"
                android:layout_below="@id/androidDIV"
                android:layout_marginTop="4dp"
                android:layout_centerHorizontal="true"/>
        </RelativeLayout>

    </RelativeLayout>
</RelativeLayout>

Is this possible?

Body:
It surely is possible. The best approach is choosing the first ImageView as reference element to which constrain everything else.

Center the TextView by assigning the left and right constraints to its image left and right edges respectively.

Then assign each image left and top contrain to their right and top edge of the previous image respectively.

Finally select all the images in the layout editor, right click and Center Horizontally (this will chain them to fit the screen width)

Example:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="match_parent">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView"
    app:layout_constraintRight_toRightOf="@+id/imageView"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView" />

<ImageView
    android:id="@+id/imageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="30dp"
    app:layout_constraintRight_toLeftOf="@+id/imageView2" />

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView2"
    app:layout_constraintRight_toRightOf="@+id/imageView2"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView2" />

<ImageView
    android:id="@+id/imageView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView"
    app:layout_constraintTop_toTopOf="@+id/imageView"
    app:layout_constraintRight_toLeftOf="@+id/imageView3" />

<TextView
    android:id="@+id/textView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView3"
    app:layout_constraintRight_toRightOf="@+id/imageView3"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView3" />

<ImageView
    android:id="@+id/imageView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView2"
    app:layout_constraintTop_toTopOf="@+id/imageView2"
    app:layout_constraintRight_toLeftOf="@+id/imageView4" />

<TextView
    android:id="@+id/textView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="@+id/imageView4"
    app:layout_constraintRight_toRightOf="@+id/imageView4"
    android:layout_marginTop="8dp"
    app:layout_constraintTop_toBottomOf="@+id/imageView4" />

<ImageView
    android:id="@+id/imageView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    app:layout_constraintLeft_toRightOf="@+id/imageView3"
    app:layout_constraintTop_toTopOf="@+id/imageView3"
    app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>


问:
Convert row to column when data are not numbers
I have a Question table, which has a unknown number of questions.(first table in the figure)

I also have an AnswerSheet table, which records student's answer to question.(second table in the figure)

```<code>Create table Question
(
    Id int,
    Text nvarchar(50),

    PRIMARY KEY (Id)
)

Create table AnswerSheet
(
    StudentId int,
    QuestionId int,
    Answer nvarchar(50),

    PRIMARY KEY (StudentId,QuestionId),
    FOREIGN KEY (QuestionId) REFERENCES Question (Id)
)

insert into Question
values(1,'What''s your age'),
      (2,'What''s your gender'),
      (3,'When do you go home'),
      ....

insert into AnswerSheet
values(500,1,'20'),
      (500,2,'Male'),
      (500,3,'5:00pm'),
      (501,1,'50'),
      (502,2,'I don''t know@@'),
      ....
</code>```

How do I write a SQL to generate a table like this?

```<code>StudentId    What's your age    What's your gender    When do you go home ...
---------    ----------------   -------------------   -------------------
500          20                 Male                  5:00pm              ...
501          50                 NULL                  NULL
502          NULL               I don''t know@@       NULL                ...
</code>```

I feel Pivot is promising but I'm not sure how to use it especially PIVOT requires an aggreation function but my data are not numbers.

答:
I know this question is answered by accepted one, but I hope this approach helps others.

simply you can achieve your goal without using Pivot, via using Group by as next:-

```<code>Select  b.StudentId,
     Min(Case a.text When 'What''s your age' Then b.answer End) 'What''s your age',
     Min(Case a.text When 'What''s your gender' Then b.answer End) 'What''s your gender',
     Min(Case a.text When 'When do you go home' Then b.answer End) 'When do you go home'
from Question a inner join AnswerSheet b
on a.id = b.Questionid
Group By StudentId
</code>```

and you mentioned unknown number of questions, so the next code for dynamic:-

```<code>DECLARE @DynamicQuestions VARCHAR(8000)

SELECT @DynamicQuestions =  Stuff(
(SELECT N' Min(Case a.text When''' + replace (Text,'''','''''')
+ ''' Then b.answer End) '''
+ replace (Text,'''','''''') + ''','
FROM Question FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,1,N'')

select @DynamicQuestions =
left(@DynamicQuestions,len(@DynamicQuestions)-1) -- for Removing last comma

exec ('Select  b.StudentId, '+ @DynamicQuestions +
'from Question a inner join AnswerSheet b
on a.id = b.Questionid
Group By StudentId' )
</code>```

Result:-

```<code>StudentId   What's your age What's your gender  When do you go home
500             20              Male                5:00pm
501             50              NULL                NULL
502             NULL        I don't know@@          NULL
</code>```

Body:
I have a Question table, which has a unknown number of questions.(first table in the figure)

I also have an AnswerSheet table, which records student's answer to question.(second table in the figure)

Create table Question
(
    Id int,
    Text nvarchar(50),

    PRIMARY KEY (Id)
)

Create table AnswerSheet
(
    StudentId int,
    QuestionId int,
    Answer nvarchar(50),

    PRIMARY KEY (StudentId,QuestionId),
    FOREIGN KEY (QuestionId) REFERENCES Question (Id)
)

insert into Question
values(1,'What''s your age'),
      (2,'What''s your gender'),
      (3,'When do you go home'),
      ....

insert into AnswerSheet
values(500,1,'20'),
      (500,2,'Male'),
      (500,3,'5:00pm'),
      (501,1,'50'),
      (502,2,'I don''t know@@'),
      ....

How do I write a SQL to generate a table like this?

StudentId    What's your age    What's your gender    When do you go home ...
---------    ----------------   -------------------   -------------------
500          20                 Male                  5:00pm              ...
501          50                 NULL                  NULL
502          NULL               I don''t know@@       NULL                ...

I feel Pivot is promising but I'm not sure how to use it especially PIVOT requires an aggreation function but my data are not numbers.

Body:
I know this question is answered by accepted one, but I hope this approach helps others.

simply you can achieve your goal without using Pivot, via using Group by as next:-

Select  b.StudentId,
     Min(Case a.text When 'What''s your age' Then b.answer End) 'What''s your age',
     Min(Case a.text When 'What''s your gender' Then b.answer End) 'What''s your gender',
     Min(Case a.text When 'When do you go home' Then b.answer End) 'When do you go home'
from Question a inner join AnswerSheet b
on a.id = b.Questionid
Group By StudentId

and you mentioned unknown number of questions, so the next code for dynamic:-

DECLARE @DynamicQuestions VARCHAR(8000)

SELECT @DynamicQuestions =  Stuff(
(SELECT N' Min(Case a.text When''' + replace (Text,'''','''''')
+ ''' Then b.answer End) '''
+ replace (Text,'''','''''') + ''','
FROM Question FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,1,N'')

select @DynamicQuestions =
left(@DynamicQuestions,len(@DynamicQuestions)-1) -- for Removing last comma

exec ('Select  b.StudentId, '+ @DynamicQuestions +
'from Question a inner join AnswerSheet b
on a.id = b.Questionid
Group By StudentId' )

Result:-

StudentId   What's your age What's your gender  When do you go home
500             20              Male                5:00pm
501             50              NULL                NULL
502             NULL        I don't know@@          NULL


问:
How do I call a class from another class(not inheritance) in Java?
I can't remember what it's called when another class's method in java for example in a main class you call the scanner class to scan in user input?</p>

答:
I think you're looking for the names of associations like aggregation and composition.
The terms are used to describe Releationships in UML</p>


问:
Rotating a triangle around a fixed point
I'm trying to recreate the game Asteroids and I'm currently getting the ship to display and move on the screen. At the moment I've got the function below which draws a triangle on the screen around an origin. What I'm trying to do is rotate the ship around the origin too.

At the moment the triangle gets completely warped by this function and I'm not sure what's going wrong. The angle I'm trying to rotate around is shipHeading and I'm trying to follow this formula:

x' = x cos f - y sin f
y' = y cos f + x sin f

where f is equal to the angle of rotation

```<code>void drawShip(void){
    int shipX = getShipX();
    int shipY = getShipY();
    int shipHeading = getShipHeading();

    int x1, y1, x2, y2, x3, y3;

    x1 = shipX;
    y1 = shipY - 20;
    x2 = shipX - 10;
    y2 = shipY + 10;
    x3 = shipX + 10;
    y3 = shipY + 10;

    screen->drawTriangle(x1, y1, x2, y2, x3, y3, RED); //pre rotation

    x1 = (x1 * cos(double(shipHeading))) - (y1 * sin(double(shipHeading)));
    y1 = (x1 * sin(double(shipHeading))) + (y1 * cos(double(shipHeading)));
    x2 = (x2 * cos(double(shipHeading))) - (y2 * sin(double(shipHeading)));
    y2 = (x2 * sin(double(shipHeading))) + (y2 * cos(double(shipHeading)));
    x3 = (x3 * cos(double(shipHeading))) - (y3 * sin(double(shipHeading)));
    y3 = (x3 * sin(double(shipHeading))) + (y3 * cos(double(shipHeading)));

    x1 *= -1;
    y1 *= -1;
    x2 *= -1;
    y2 *= -1;
    x3 *= -1;
    y3 *= -1;

    screen->drawTriangle(x1, y1, x2, y2, x3, y3, BLUE); //post rotation
</code>```

答:
A few problems I see in your math:

You are rotating your points while you are changing them. This means that while the X may be computed correctly, the computation of the new Y will be using the new X instead of the original value of X. That is wrong, and you need to save the old point when computing the new point. See an example of doing this in rotatePoint() below.

You need to specify a pivot point when rotating. Again, refer to rotatePoint to see how this is done. This is based on the algorithm posted here.

cos() and sin() expect the angle to be in radian units. Not sure if you are already taking this into account with shipHeading, but it seems unlikely since it is an int. In my solution, I assume shipHeading is in degrees and convert it to radians before invoking the trig functions.

Your tranlation idea of multiplying the points by -1 seems strange, and would result in a vary chaotic looking flip. In asteroids, this should be adding an int to the points based on current speed, and acceleration.

The step in creating an algorithm is encapsulation. Do not try to do everything in one function with all ints. Create abstract data types like Point to represent an (x,y) pair.

```<code>typedef struct {
          int x;
          int y;
        } Point;
</code>```

Then create another abstract data type called Ship to represent a ship that is made up of three points.

```<code>typedef struct {
           Point top;
           Point left;
           Point right;
        } Ship;
</code>```

Next, create a helper function to abstract rotating points around a pivot point. Then create a high level function that rotates the ship around a pivot point, that calls the roatePoint function to rotate each of its three points.

By abstracting the details, the algorithm becomes clear. It also means that bug fixes show up in one place, instead of many. For example, cos() and sin() expect the rotation to be expressed in Radians, but we typically code thinking in terms of degrees of rotation. By isolating the rotation into PivotPoint(), all the math is located in just this one place.

Here is my solution, with several of the missing functions stubbed:

```<code>#include <stdio.h>
#include <math.h>

typedef struct {
          int x;
          int y;
        } Point;

typedef struct {
           Point top;
           Point left;
           Point right;
        } Ship;

// See https://stackoverflow.com/a/2259502/6693299 for point rotation algorithm
Point rotatePoint(Point pivotPoint, Point point, int shipHeading)
{
 Point newPoint = {0};

 // Translate point back to the origin
 point.x -= pivotPoint.x;
 point.y -= pivotPoint.y;

 // Cos and Sin expect angle in radians, but let's use shipHeading in degrees
 // To convert shipHeading in degrees to radians, multiply by 0.0174533
 double radians = ((double) shipHeading) * 0.0174533;

 // Rotate Point
 // Compute new point based on old point and shipHeading
 newPoint.x = (point.x * cos(radians)) - (point.y * sin(radians));
 newPoint.y = (point.x * sin(radians)) + (point.y * cos(radians));

 // Translate the point back
 newPoint.x += pivotPoint.x;
 newPoint.y += pivotPoint.y;

 return newPoint;
}

Ship rotateShip(Ship* ship, int shipHeading)
{
 Ship newPosition = {0};

 // Rotate ship by shipHeading degrees, centered around top
 newPosition.top   = rotatePoint(ship->top, ship->top,   shipHeading);
 newPosition.left  = rotatePoint(ship->top, ship->left,  shipHeading);
 newPosition.right = rotatePoint(ship->top, ship->right, shipHeading);

 return newPosition;
}

Point newPoint(int x, int y)
{
 Point point = {0};
 point.x = x;
 point.y = y;
 return point;
}

Ship newShip(int shipX, int shipY)
{
 Ship newShip    = {0};
 newShip.top     = newPoint(shipX, shipY);
 newShip.left    = newPoint(shipX + 10, shipY - 5);
 newShip.right   = newPoint(shipX + 10, shipY + 5);
 return newShip;
}

// stubs
int getShipX(void) { return 10;}
int getShipY(void) { return 10;}
int getShipHeading(void) {return 90;} // Expressed in degrees

void drawTriangle(int x1, int y1, int x2, int y2, int x3,
{
 // stub
 printf("Ship location: (%d,%d) (%d,%d) (%d,%d)\n", x1,y1, x2,y2, x3,y3);
}

void drawShip(void){
    Ship ship        = newShip(getShipX(), getShipY());
    int  shipHeading = getShipHeading();
    int  RED         = 0; // stub

    drawTriangle(ship.top.x,   ship.top.y,
                 ship.left.x,  ship.left.y,
                 ship.right.x, ship.right.y, RED); //pre rotation

    ship = rotateShip(&ship, shipHeading);

#if 0
    // Multiplying by -1 will Flip the ship?
    // Use += instead to move the ship up by one
    // Better to use a function like moveShip()
    ship.top.x   += -1;
    ship.top.y   += -1;
    ship.left.x  += -1;
    ship.left.y  += -1;
    ship.right.x += -1;
    ship.right.y += -1;
#endif

    drawTriangle(ship.top.x,   ship.top.y,
                 ship.left.x,  ship.left.y,
                 ship.right.x, ship.right.y, RED); //pre rotation
}

int main(int argc, char** argv)
{
 drawShip();
}
</code>```

The output first displays the ship's three points (top) (left) (right) which I default to (10,10) (20,5) (20,15) using X windows notation (X,Y) where the top left portion of the screen is (0,0). The second line of output are the points after a 90 degree rotate around the top point (10,10). You can pick any pivot point. For more on Point Rotation, refer to this stackOverflow article.

```<code>scott> gcc asteroids.c -lm
scott> a.out
Ship location: (10,10) (20,5) (20,15)
Ship location: (10,10) (14,20) (5,19)
scott>
</code>```

Hope this helps as a starting point. Make changes to fit into your framework.

Body:
I'm trying to recreate the game Asteroids and I'm currently getting the ship to display and move on the screen. At the moment I've got the function below which draws a triangle on the screen around an origin. What I'm trying to do is rotate the ship around the origin too.

At the moment the triangle gets completely warped by this function and I'm not sure what's going wrong. The angle I'm trying to rotate around is shipHeading and I'm trying to follow this formula:

x' = x cos f - y sin f
y' = y cos f + x sin f

where f is equal to the angle of rotation

void drawShip(void){
    int shipX = getShipX();
    int shipY = getShipY();
    int shipHeading = getShipHeading();

    int x1, y1, x2, y2, x3, y3;

    x1 = shipX;
    y1 = shipY - 20;
    x2 = shipX - 10;
    y2 = shipY + 10;
    x3 = shipX + 10;
    y3 = shipY + 10;

    screen->drawTriangle(x1, y1, x2, y2, x3, y3, RED); //pre rotation

    x1 = (x1 * cos(double(shipHeading))) - (y1 * sin(double(shipHeading)));
    y1 = (x1 * sin(double(shipHeading))) + (y1 * cos(double(shipHeading)));
    x2 = (x2 * cos(double(shipHeading))) - (y2 * sin(double(shipHeading)));
    y2 = (x2 * sin(double(shipHeading))) + (y2 * cos(double(shipHeading)));
    x3 = (x3 * cos(double(shipHeading))) - (y3 * sin(double(shipHeading)));
    y3 = (x3 * sin(double(shipHeading))) + (y3 * cos(double(shipHeading)));

    x1 *= -1;
    y1 *= -1;
    x2 *= -1;
    y2 *= -1;
    x3 *= -1;
    y3 *= -1;

    screen->drawTriangle(x1, y1, x2, y2, x3, y3, BLUE); //post rotation

Body:
A few problems I see in your math:

You are rotating your points while you are changing them. This means that while the X may be computed correctly, the computation of the new Y will be using the new X instead of the original value of X. That is wrong, and you need to save the old point when computing the new point. See an example of doing this in rotatePoint() below.

You need to specify a pivot point when rotating. Again, refer to rotatePoint to see how this is done. This is based on the algorithm posted here.

cos() and sin() expect the angle to be in radian units. Not sure if you are already taking this into account with shipHeading, but it seems unlikely since it is an int. In my solution, I assume shipHeading is in degrees and convert it to radians before invoking the trig functions.

Your tranlation idea of multiplying the points by -1 seems strange, and would result in a vary chaotic looking flip. In asteroids, this should be adding an int to the points based on current speed, and acceleration.

The step in creating an algorithm is encapsulation. Do not try to do everything in one function with all ints. Create abstract data types like Point to represent an (x,y) pair.

typedef struct {
          int x;
          int y;
        } Point;

Then create another abstract data type called Ship to represent a ship that is made up of three points.

typedef struct {
           Point top;
           Point left;
           Point right;
        } Ship;

Next, create a helper function to abstract rotating points around a pivot point. Then create a high level function that rotates the ship around a pivot point, that calls the roatePoint function to rotate each of its three points.

By abstracting the details, the algorithm becomes clear. It also means that bug fixes show up in one place, instead of many. For example, cos() and sin() expect the rotation to be expressed in Radians, but we typically code thinking in terms of degrees of rotation. By isolating the rotation into PivotPoint(), all the math is located in just this one place.

Here is my solution, with several of the missing functions stubbed:

#include <stdio.h>
#include <math.h>

typedef struct {
          int x;
          int y;
        } Point;

typedef struct {
           Point top;
           Point left;
           Point right;
        } Ship;

// See https://stackoverflow.com/a/2259502/6693299 for point rotation algorithm
Point rotatePoint(Point pivotPoint, Point point, int shipHeading)
{
 Point newPoint = {0};

 // Translate point back to the origin
 point.x -= pivotPoint.x;
 point.y -= pivotPoint.y;

 // Cos and Sin expect angle in radians, but let's use shipHeading in degrees
 // To convert shipHeading in degrees to radians, multiply by 0.0174533
 double radians = ((double) shipHeading) * 0.0174533;

 // Rotate Point
 // Compute new point based on old point and shipHeading
 newPoint.x = (point.x * cos(radians)) - (point.y * sin(radians));
 newPoint.y = (point.x * sin(radians)) + (point.y * cos(radians));

 // Translate the point back
 newPoint.x += pivotPoint.x;
 newPoint.y += pivotPoint.y;

 return newPoint;
}

Ship rotateShip(Ship* ship, int shipHeading)
{
 Ship newPosition = {0};

 // Rotate ship by shipHeading degrees, centered around top
 newPosition.top   = rotatePoint(ship->top, ship->top,   shipHeading);
 newPosition.left  = rotatePoint(ship->top, ship->left,  shipHeading);
 newPosition.right = rotatePoint(ship->top, ship->right, shipHeading);

 return newPosition;
}

Point newPoint(int x, int y)
{
 Point point = {0};
 point.x = x;
 point.y = y;
 return point;
}

Ship newShip(int shipX, int shipY)
{
 Ship newShip    = {0};
 newShip.top     = newPoint(shipX, shipY);
 newShip.left    = newPoint(shipX + 10, shipY - 5);
 newShip.right   = newPoint(shipX + 10, shipY + 5);
 return newShip;
}

// stubs
int getShipX(void) { return 10;}
int getShipY(void) { return 10;}
int getShipHeading(void) {return 90;} // Expressed in degrees

void drawTriangle(int x1, int y1, int x2, int y2, int x3,
{
 // stub
 printf("Ship location: (%d,%d) (%d,%d) (%d,%d)\n", x1,y1, x2,y2, x3,y3);
}

void drawShip(void){
    Ship ship        = newShip(getShipX(), getShipY());
    int  shipHeading = getShipHeading();
    int  RED         = 0; // stub

    drawTriangle(ship.top.x,   ship.top.y,
                 ship.left.x,  ship.left.y,
                 ship.right.x, ship.right.y, RED); //pre rotation

    ship = rotateShip(&ship, shipHeading);

#if 0
    // Multiplying by -1 will Flip the ship?
    // Use += instead to move the ship up by one
    // Better to use a function like moveShip()
    ship.top.x   += -1;
    ship.top.y   += -1;
    ship.left.x  += -1;
    ship.left.y  += -1;
    ship.right.x += -1;
    ship.right.y += -1;
#endif

    drawTriangle(ship.top.x,   ship.top.y,
                 ship.left.x,  ship.left.y,
                 ship.right.x, ship.right.y, RED); //pre rotation
}

int main(int argc, char** argv)
{
 drawShip();
}

The output first displays the ship's three points (top) (left) (right) which I default to (10,10) (20,5) (20,15) using X windows notation (X,Y) where the top left portion of the screen is (0,0). The second line of output are the points after a 90 degree rotate around the top point (10,10). You can pick any pivot point. For more on Point Rotation, refer to this stackOverflow article.

scott> gcc asteroids.c -lm
scott> a.out
Ship location: (10,10) (20,5) (20,15)
Ship location: (10,10) (14,20) (5,19)
scott>

Hope this helps as a starting point. Make changes to fit into your framework.


问:
Dealing with disassociated records in a poorly designed database

Overview

I have inherited a website that allows users to order customised products. The customisations were saved in a way that disassociates them from their record. I would like to modify the db so these records can be associated.

Example

Users can get Product #1 "stock", or customise it, changing as many as 10 different properties. Let's say color, fabric, width, height etc.

Orders can, and regularly do, contain multiple products, each of which may be customised.

Additionally, users can save their orders, so they can re-order later.

When the database was designed, the details of the order was neatly organised into individual columns. Customer name, address, payment type etc. But the list of products and more notably their customisations were saved as a JSON string in a single column. For ease, let's call this column the "cart".

Basically, the order table has a column cart and the cart column contains a JSON-formatted list of products and customisations.

Unfortunately, the JSON object has reference ids to the product table, but lacks references to the customisation table. Instead it uses a bunch of strings meant for a human to read. Fortunately those strings exist in the customisation table, but they were written as the cart was created.

The problem we face is that the list of customisations can be changed by a CMS. So far, they haven't been changed.  But they will need to be soon and that's going to cause problems:

Problems

If a customisation option is removed (say, a fabric option) and a customer re-orders from an old saved order, we need to be able to parse the cart, detect this and warn them of the change.

Customisations are currently immutable. Once a product is added to the cart, it cannot be changed. Users need to delete and re-add to make a single change. Poor UX.

If anyone changes the human-readable text on a customisation we're dead. ☠

Questions

How would you design this if you were staring from scratch?

How might we go about converting the current implementation and legacy data to this new schema?

I don't know if stack is notable, but we're on Postgres and Django-Python.

答:
I would implement this with the following tables:

```<code>Products {
  productId                   // primary key
  name
  price
}

Customization_Types {
  customizationTypeId         // primary key
  name                        // e.g. COLOR, FABRIC, LENGTH
}

Customizations {
  customizationId             // primary key
  customizationTypeId         // foreign key
  value                       // e.g. BEIGE, VELVET, 8
}

Product_Customizations {
  productCustomizationId      // primary key
  productId                   // foreign key
  customizationId             // foreign key
  priceModifier               // price markup for applying the customization
  isValid                     // false if this record is invalid/obsolete
}

Orders {
  orderId                     // primary key
  customerId                  // foreign key
}

Product_Orders {
  productOrderId              // primary key
  orderId                     // foreign key
  productId                   // foreign key
  quantity
}

Customization_Orders {
  customizationOrderId        // primary key
  productOrderId              // foreign key
  productCustomizationId      // foreign key
}
</code>```

The Products table contains the data for your base products - name, price, etc

The Customization_Types table contains the type names for your different customizations - COLOR, FABRIC, LENGTH, etc

The Customizations table contains a link to a customizationTypeId as well as a legal value - I'm assuming that users can't enter arbitrary numerical values (for e.g. LENGTH or WIDTH) i.e. they're given a drop-down box instead of a text box, however if they can enter arbitrary numerical data then you'll need MIN/MAX fields that are null for named constraints (so e.g. you could have Type:COLOR/Value:BEIGE/Min:NULL/Max:NULL or Type:LENGTH/Value:NULL/Min:4/Max:8)

The Product_Customizations table links a Customization to a Product, so for example if ProductX can come in BEIGE then you would create a Product_Customization record that links ProductX to BEIGE.

The Orders table just contains an orderId and anything else relevant to the order (e.g. a link to the customerId and shippingAddressId)

Product_Orders links a product to an order

Customization_Orders links a Product_Customization to a Product_Order

Let's say a customer orders ProductX in BEIGE and LENGTH=8, then you would create an Order record, a Product_Order record with a link to ProductX, and two Customization_Order records - one linked to COLOR=BEIGE and one linked to LENGTH=8.

This should make it easy to modify a product's customizations without having to reload the entire product - the user can modify color to COLOR=RED without touching the length customization (delete the old Customization_Order:COLOR=BEIGE record and create a new COLOR=RED record), or the user can remove the length customization without touching the color customization (delete the old Customization_Order:LENGTH=8 record).

When reloading an old order/product you can quickly verify that the same productCustomizationIds still apply to the product in question, else flag the user.  Additionally, you can flag the user if the customization still applies but the customization's price modifier has changed.

As far as converting the legacy data, I'm not familiar with Python but I do have experience with reading JSON via Java and I'm assuming that Python offers similar if not better libraries for this.  The trick is going to be matching the existing data to pre-loaded Product_Customization data - if the data fails to match then create a new Product_Customization row corresponding to it with isValid=FALSE (this is assuming that the customization in question is no longer offered), and when you get a chance manually iterate through the invalid Product_Customization rows to ensure that these really are unmatched customizations and not just parsing errors.

Body:
I would implement this with the following tables:

Products {
  productId                   // primary key
  name
  price
}

Customization_Types {
  customizationTypeId         // primary key
  name                        // e.g. COLOR, FABRIC, LENGTH
}

Customizations {
  customizationId             // primary key
  customizationTypeId         // foreign key
  value                       // e.g. BEIGE, VELVET, 8
}

Product_Customizations {
  productCustomizationId      // primary key
  productId                   // foreign key
  customizationId             // foreign key
  priceModifier               // price markup for applying the customization
  isValid                     // false if this record is invalid/obsolete
}

Orders {
  orderId                     // primary key
  customerId                  // foreign key
}

Product_Orders {
  productOrderId              // primary key
  orderId                     // foreign key
  productId                   // foreign key
  quantity
}

Customization_Orders {
  customizationOrderId        // primary key
  productOrderId              // foreign key
  productCustomizationId      // foreign key
}

The Products table contains the data for your base products - name, price, etc

The Customization_Types table contains the type names for your different customizations - COLOR, FABRIC, LENGTH, etc

The Customizations table contains a link to a customizationTypeId as well as a legal value - I'm assuming that users can't enter arbitrary numerical values (for e.g. LENGTH or WIDTH) i.e. they're given a drop-down box instead of a text box, however if they can enter arbitrary numerical data then you'll need MIN/MAX fields that are null for named constraints (so e.g. you could have Type:COLOR/Value:BEIGE/Min:NULL/Max:NULL or Type:LENGTH/Value:NULL/Min:4/Max:8)

The Product_Customizations table links a Customization to a Product, so for example if ProductX can come in BEIGE then you would create a Product_Customization record that links ProductX to BEIGE.

The Orders table just contains an orderId and anything else relevant to the order (e.g. a link to the customerId and shippingAddressId)

Product_Orders links a product to an order

Customization_Orders links a Product_Customization to a Product_Order

Let's say a customer orders ProductX in BEIGE and LENGTH=8, then you would create an Order record, a Product_Order record with a link to ProductX, and two Customization_Order records - one linked to COLOR=BEIGE and one linked to LENGTH=8.

This should make it easy to modify a product's customizations without having to reload the entire product - the user can modify color to COLOR=RED without touching the length customization (delete the old Customization_Order:COLOR=BEIGE record and create a new COLOR=RED record), or the user can remove the length customization without touching the color customization (delete the old Customization_Order:LENGTH=8 record).

When reloading an old order/product you can quickly verify that the same productCustomizationIds still apply to the product in question, else flag the user.  Additionally, you can flag the user if the customization still applies but the customization's price modifier has changed.

As far as converting the legacy data, I'm not familiar with Python but I do have experience with reading JSON via Java and I'm assuming that Python offers similar if not better libraries for this.  The trick is going to be matching the existing data to pre-loaded Product_Customization data - if the data fails to match then create a new Product_Customization row corresponding to it with isValid=FALSE (this is assuming that the customization in question is no longer offered), and when you get a chance manually iterate through the invalid Product_Customization rows to ensure that these really are unmatched customizations and not just parsing errors.